ioservice.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. /**
  19. * An asio::io_service maintains a queue of asynchronous tasks and invokes them
  20. * when they are ready to run. Async network IO handlers become runnable when
  21. * the associated IO operation has completed. The hdfs::IoService is a thin
  22. * wrapper over that object to make it easier to add logging and instrumentation
  23. * to tasks that have been queued.
  24. *
  25. * Lifecycle management:
  26. * -The IoService *shall* outlive any tasks it owns. Deleting a task
  27. * before it has been run **will** result in dangling reference issues.
  28. * -Dependencies (including transitive dependencies) of pending tasks
  29. * *shall* outlive the task. Failure to ensure this **will** result in
  30. * danging reference issues.
  31. * -libhdfs++ uses shared_ptr/weak_ptr heavily as a mechanism to ensure
  32. * liveness of dependencies.
  33. * -refcounted pointers in lambda capture lists have a poor track record
  34. * for ensuring liveness in this library; it's easy to omit them because
  35. * the capture list isn't context aware. Developers are encouraged to
  36. * write callable classes that explicitly list dependencies.
  37. *
  38. * Constraints on tasks:
  39. * -Tasks and async callbacks *shall* never do blocking IO or sleep().
  40. * At best this hurts performance by preventing worker threads from doing
  41. * useful work. It may also cause situations that look like deadlocks
  42. * if the worker thread is stalled for long enough.
  43. * -Tasks and async callbacks *shall* not acquire locks that guard resources
  44. * that might be unavailable for an unknown amount of time. Lock acquisition
  45. * when accessing shared data structures is acceptable and is often required.
  46. * -Tasks and async callbacks *should* not allow exceptions to escape their
  47. * scope since tasks will be executed on a different stack then where they
  48. * were created. The exception will be caught by the IoService rather than
  49. * being forwarded to the next task.
  50. * -Tasks and async callbacks *should* not rely on thread local storage for
  51. * ancillary context. The IoService does not support any sort of thread
  52. * affinity that would guarantee tasks Post()ed from one thread will always
  53. * be executed on the same thread. Applications that only use a single
  54. * worker thread may use TLS but developers should be mindful that throughput
  55. * can no longer be scaled by adding threads.
  56. **/
  57. #ifndef INCLUDE_HDFSPP_IOSERVICE_H_
  58. #define INCLUDE_HDFSPP_IOSERVICE_H_
  59. #include <memory>
  60. // forward decl
  61. namespace asio {
  62. class io_service;
  63. }
  64. namespace hdfs {
  65. // (Un)comment this to determine if issues are due to concurrency or logic faults
  66. // If tests still fail with concurrency disabled it's most likely a logic bug
  67. #define DISABLE_CONCURRENT_WORKERS
  68. class IoService : public std::enable_shared_from_this<IoService>
  69. {
  70. public:
  71. static IoService *New();
  72. static std::shared_ptr<IoService> MakeShared();
  73. virtual ~IoService();
  74. /**
  75. * Start up as many threads as there are logical processors.
  76. * Return number of threads created.
  77. **/
  78. virtual unsigned int InitDefaultWorkers() = 0;
  79. /**
  80. * Initialize with thread_count handler threads.
  81. * If thread count is less than one print a log message and default to one thread.
  82. * Return number of threads created.
  83. **/
  84. virtual unsigned int InitWorkers(unsigned int thread_count) = 0;
  85. /**
  86. * Add a worker thread to existing pool.
  87. * Return true on success, false otherwise.
  88. **/
  89. virtual bool AddWorkerThread() = 0;
  90. /**
  91. * Return the number of worker threads in use.
  92. **/
  93. virtual unsigned int GetWorkerThreadCount() = 0;
  94. /**
  95. * Enqueue an item for deferred execution. Non-blocking.
  96. * Task will be invoked from outside of the calling context.
  97. **/
  98. virtual void PostTask(std::function<void(void)> asyncTask) = 0;
  99. /**
  100. * Provide type erasure for lambdas defined inside the argument list.
  101. **/
  102. template <typename LambdaInstance>
  103. inline void PostLambda(LambdaInstance&& func)
  104. {
  105. std::function<void(void)> typeEraser = func;
  106. this->PostTask(func);
  107. }
  108. /**
  109. * Run the asynchronous tasks associated with this IoService.
  110. **/
  111. virtual void Run() = 0;
  112. /**
  113. * Stop running asynchronous tasks associated with this IoService.
  114. * All worker threads will return as soon as they finish executing their current task.
  115. **/
  116. virtual void Stop() = 0;
  117. /**
  118. * Access underlying io_service object. Only to be used in asio library calls.
  119. * After HDFS-11884 is complete only tests should need direct access to the asio::io_service.
  120. **/
  121. virtual asio::io_service& GetRaw() = 0;
  122. };
  123. } // namespace hdfs
  124. #endif // include guard