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, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 #ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 21 #define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1 22 23 #include <functional> 24 #include <memory> 25 26 #include <thrift/concurrency/Thread.h> 27 28 namespace apache { 29 namespace thrift { 30 namespace concurrency { 31 32 /** 33 * Convenient implementation of Runnable that will execute arbitrary callbacks. 34 * Interfaces are provided to accept both a generic 'void(void)' callback, and 35 * a 'void* (void*)' pthread_create-style callback. 36 * 37 * Example use: 38 * void* my_thread_main(void* arg); 39 * shared_ptr<ThreadFactory> factory = ...; 40 * // To create a thread that executes my_thread_main once: 41 * shared_ptr<Thread> thread = factory->newThread( 42 * FunctionRunner::create(my_thread_main, some_argument)); 43 * thread->start(); 44 * 45 * bool A::foo(); 46 * A* a = new A(); 47 * // To create a thread that executes a.foo() every 100 milliseconds: 48 * factory->newThread(FunctionRunner::create( 49 * std::bind(&A::foo, a), 100))->start(); 50 * 51 */ 52 53 class FunctionRunner : public Runnable { 54 public: 55 // This is the type of callback 'pthread_create()' expects. 56 typedef void* (*PthreadFuncPtr)(void* arg); 57 // This a fully-generic void(void) callback for custom bindings. 58 typedef std::function<void()> VoidFunc; 59 60 typedef std::function<bool()> BoolFunc; 61 62 /** 63 * Syntactic sugar to make it easier to create new FunctionRunner 64 * objects wrapped in shared_ptr. 65 */ create(const VoidFunc & cob)66 static std::shared_ptr<FunctionRunner> create(const VoidFunc& cob) { 67 return std::shared_ptr<FunctionRunner>(new FunctionRunner(cob)); 68 } 69 create(PthreadFuncPtr func,void * arg)70 static std::shared_ptr<FunctionRunner> create(PthreadFuncPtr func, void* arg) { 71 return std::shared_ptr<FunctionRunner>(new FunctionRunner(func, arg)); 72 } 73 74 private: pthread_func_wrapper(PthreadFuncPtr func,void * arg)75 static void pthread_func_wrapper(PthreadFuncPtr func, void* arg) { 76 // discard return value 77 func(arg); 78 } 79 80 public: 81 /** 82 * Given a 'pthread_create' style callback, this FunctionRunner will 83 * execute the given callback. Note that the 'void*' return value is ignored. 84 */ FunctionRunner(PthreadFuncPtr func,void * arg)85 FunctionRunner(PthreadFuncPtr func, void* arg) 86 : func_(std::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {} 87 88 /** 89 * Given a generic callback, this FunctionRunner will execute it. 90 */ FunctionRunner(const VoidFunc & cob)91 FunctionRunner(const VoidFunc& cob) : func_(cob), intervalMs_(-1) {} 92 93 /** 94 * Given a bool foo(...) type callback, FunctionRunner will execute 95 * the callback repeatedly with 'intervalMs' milliseconds between the calls, 96 * until it returns false. Note that the actual interval between calls will 97 * be intervalMs plus execution time of the callback. 98 */ FunctionRunner(const BoolFunc & cob,int intervalMs)99 FunctionRunner(const BoolFunc& cob, int intervalMs) : repFunc_(cob), intervalMs_(intervalMs) {} 100 run()101 void run() override { 102 if (repFunc_) { 103 while (repFunc_()) { 104 THRIFT_SLEEP_USEC(intervalMs_ * 1000); 105 } 106 } else { 107 func_(); 108 } 109 } 110 111 private: 112 VoidFunc func_; 113 BoolFunc repFunc_; 114 int intervalMs_; 115 }; 116 } 117 } 118 } // apache::thrift::concurrency 119 120 #endif // #ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 121