ioservice.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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 <functional>
  60. #include <memory>
  61. #include <boost/asio/io_service.hpp>
  62. namespace hdfs {
  63. // (Un)comment this to determine if issues are due to concurrency or logic faults
  64. // If tests still fail with concurrency disabled it's most likely a logic bug
  65. #define DISABLE_CONCURRENT_WORKERS
  66. class IoService : public std::enable_shared_from_this<IoService>
  67. {
  68. public:
  69. static IoService *New();
  70. static std::shared_ptr<IoService> MakeShared();
  71. virtual ~IoService();
  72. /**
  73. * Start up as many threads as there are logical processors.
  74. * Return number of threads created.
  75. **/
  76. virtual unsigned int InitDefaultWorkers() = 0;
  77. /**
  78. * Initialize with thread_count handler threads.
  79. * If thread count is less than one print a log message and default to one thread.
  80. * Return number of threads created.
  81. **/
  82. virtual unsigned int InitWorkers(unsigned int thread_count) = 0;
  83. /**
  84. * Add a worker thread to existing pool.
  85. * Return true on success, false otherwise.
  86. **/
  87. virtual bool AddWorkerThread() = 0;
  88. /**
  89. * Return the number of worker threads in use.
  90. **/
  91. virtual unsigned int GetWorkerThreadCount() = 0;
  92. /**
  93. * Enqueue an item for deferred execution. Non-blocking.
  94. * Task will be invoked from outside of the calling context.
  95. **/
  96. virtual void PostTask(std::function<void(void)> asyncTask) = 0;
  97. /**
  98. * Provide type erasure for lambdas defined inside the argument list.
  99. **/
  100. template <typename LambdaInstance>
  101. inline void PostLambda(LambdaInstance&& func)
  102. {
  103. std::function<void(void)> typeEraser = func;
  104. this->PostTask(func);
  105. }
  106. /**
  107. * Run the asynchronous tasks associated with this IoService.
  108. **/
  109. virtual void Run() = 0;
  110. /**
  111. * Stop running asynchronous tasks associated with this IoService.
  112. * All worker threads will return as soon as they finish executing their current task.
  113. **/
  114. virtual void Stop() = 0;
  115. /**
  116. * Access underlying io_service object. Only to be used in asio library calls.
  117. * After HDFS-11884 is complete only tests should need direct access to the asio::io_service.
  118. **/
  119. virtual boost::asio::io_service& GetRaw() = 0;
  120. };
  121. } // namespace hdfs
  122. #endif // include guard