input: Write a python function to create an instance of `AsyncIOExecutor`, submit an async function that returns a value, and gather results of multiple async functions.
  assert asyncio.run(test_async_executor()) == [10, 20, 30]
  
  ```python
  async def test_async_executor():
      executor = AsyncIOExecutor(2)
      
      async def async_func(value):
          await asyncio.sleep(1)
          return value
      
      fut1 = executor.submit(async_func(10))
      fut2 = executor.submit(async_func(20))
      fut3 = executor.submit(async_func(30))
      
      return await executor.gather([fut1, fut2, fut3])
output: def AsyncIOExecutor(max_concurrent_tasks):
      import asyncio
      from concurrent.futures import ThreadPoolExecutor
  
      class Executor:
          def __init__(self, max_concurrent_tasks):
              self.loop = asyncio.get_event_loop()
              self.executor = ThreadPoolExecutor(max_concurrent_tasks)
  
          async def gather(self, tasks):
              return await asyncio.gather(*tasks)
  
          def submit(self, coro):
              return self.loop.run_in_executor(self.executor, asyncio.run, coro)
  
      return Executor(max_concurrent_tasks)
  
  import asyncio