diff --git a/include/lockvoker.h b/include/lockvoker.h new file mode 100644 index 0000000..c637e90 --- /dev/null +++ b/include/lockvoker.h @@ -0,0 +1,67 @@ +#ifndef LOCKVOKER_H +#define LOCKVOKER_H + +#include +#include +#include +#include +#include + +namespace smo { + +/** + * @brief LockerAndInvoker - Template class for lockvoking mechanism + * + * This class wraps a std::bind result and provides locking functionality. + * When locks cannot be acquired, the object re-posts itself to the io_service + * queue, implementing the "spinqueueing" pattern. + */ +template +class LockerAndInvoker +{ +public: + /** + * @brief Constructor that immediately posts to io_service + * @param serializedContinuation Reference to the serialized continuation + * containing LockSpec and target io_service + * @param invocationTarget The std::bind result to invoke when locks are acquired + */ + LockerAndInvoker( + SerializedAsynchronousContinuation& serializedContinuation, + InvocationTargetT invocationTarget) + : serializedContinuation(serializedContinuation), + invocationTarget(std::move(invocationTarget)) + { + post(); + } + + /** + * @brief Post this object to the io_service + */ + void post() + { serializedContinuation.caller->getIoService().post(*this); } + + /** + * @brief Function call operator - tries to acquire locks and either invokes + * the target or re-posts itself + */ + void operator()() + { + if (!serializedContinuation.tryAcquire()) + { + // Re-post ourselves to try again later + post(); + return; + } + + invocationTarget(); + } + +private: + SerializedAsynchronousContinuation& serializedContinuation; + InvocationTargetT invocationTarget; +}; + +} // namespace smo + +#endif // LOCKVOKER_H