| /* |
| * Copyright 2015 Twitter, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Generic callback definitions. In their simplest form they can be used as an |
| // alternative to the |
| // |
| // void (*func)() |
| // |
| // counterparts of C. |
| // |
| // More interesting however is their usage when functions expect arguments. |
| // |
| // Lets say that you want to pass a function to a routine that needs to execute |
| // it once when certain conditions are met. In typical C, you would do something |
| // like |
| // |
| // void Routine(int arg, int arg2, void (*func)()) |
| // { |
| // ... some code ... |
| // func(); |
| // } |
| // |
| // This approach has two issues - |
| // - what if you don't know the signature of the function? |
| // - What if func can take one or more arguments? |
| // |
| // In such cases, using our Callbacks you can do the following |
| // |
| // void Routine(int arg, int arg2, CallBack* a) |
| // { |
| // ... some code ... |
| // a->Run(); |
| // } |
| // |
| // Now when you actually pass on the Callback during invocation, you can do |
| // something like |
| // |
| // CallBack* cb = CreateCallback(void (*func)()); |
| // |
| // or |
| // |
| // CallBack* cb = CreateCallback(void (*func)(int), 10); |
| // Routine(arg, arg2, cb); |
| // |
| // Routine doesn't have to know the signature of the function, nor does it need |
| // to remember any arguments that the function requires. The CallBack cb is |
| // destroyed after its invocation so one doesn't need to worry abt cleaning |
| // it up. |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| #ifndef HERON_CALLBACK_H_ |
| #define HERON_CALLBACK_H_ |
| |
| #include <functional> |
| |
| /** |
| * Basic CallBack definition. |
| * There are two types of CallBacks. |
| * - Temporary callback - the CallBack gets deleted as soon as its invoked. |
| * - Persistent callBack - the CallBack remains across multiple invocations. |
| */ |
| class CallBack { |
| public: |
| // Constructor. Users should use the CreateCallback functions detailed below. |
| CallBack(bool persist, std::function<void()> f) |
| : persistent_(persist), bind_(f) {} |
| |
| virtual ~CallBack() {} |
| |
| // The main exported function |
| void Run() { |
| // In case of persistent callbacks, the RunCallback might delete itself. |
| // In that case after RunCallback returns it is not safe to access |
| // the class member persistent_. So make a copy now. |
| bool persist = persistent_; |
| bind_(); |
| if (!persist) { |
| delete this; |
| } |
| } |
| |
| // Return whether the callback is temporary or permanent. |
| bool isPersistent() const { return persistent_; } |
| |
| void makePersistent() { persistent_ = true; } |
| |
| private: |
| bool persistent_; |
| std::function<void()> bind_; |
| }; |
| |
| // |
| // Helper functions to create callbacks |
| // |
| template <typename... C> |
| inline |
| CallBack* CreateCallback(void (*cb)(C... args), C... args) { |
| return new CallBack(false, std::bind(cb, args...)); |
| } |
| |
| template <typename... C> |
| inline |
| CallBack* CreatePersistentCallback(void (*cb)(C... args), C... args) { |
| return new CallBack(true, std::bind(cb, args...)); |
| } |
| |
| #endif // HERON_CALLBACK_H_ |