// Copyright (c) 2005-2007 Hartmut Kaiser (hartmut.kaiser@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #if !defined(SAGA_IMPL_ENGINE_SYNC_ASYNC_HPP) #define SAGA_IMPL_ENGINE_SYNC_ASYNC_HPP // #include /////////////////////////////////////////////////////////////////////////////// namespace saga { namespace impl { enum run_mode { Unknown = -1, Sync_Sync = 0, Sync_ASync = 1, ASync_Sync = 2, ASync_ASync = 3 }; // in general: // Adaptors can provide their API functions synchronously or asynchronously // or both of them. // Towards the application, the engine has to provide all api functions // synchronously, asynchronously and as a Task (asynchronously but not yet // started). // The following code dispatches between those possibilities. /////////////////////////////////////////////////////////////////////////// // need sync, have sync // the application wants a synchronous call, the adaptor provides a synchronous // one. // so there is nothing to do, we have only to call the function. template inline saga::task sync_sync (TR1::shared_ptr cpi_instance, void (FuncBase::*sync_func)(FuncRetVal), RetVal ret) { boost/*::phoenix*/::bind (sync_func, cpi_instance, ret) (); return (saga::task (saga::task::Done)); } /////////////////////////////////////////////////////////////////////////// // need async, have sync // the application wants a asynchronous call, but the adaptor provides a // only a synchronous one. // so the call is executed in a thread, and by that way made asynchronous. template inline saga::task async_sync (TR1::shared_ptr cpi_instance, void (FuncBase::* sync_func)(FuncRetVal), RetVal ret, char const *func_name_, bool (FuncBase::*prep_func)(FuncRetVal, saga::uuid) = NULL) { return (saga::adaptors::task(func_name_, cpi_instance, sync_func, ret, prep_func)); } /////////////////////////////////////////////////////////////////////////// // need sync, have async // the application wants a synchronous call, the adaptor provides a asynchronous // one. // so, we wait for the call to finish template inline saga::task sync_async (TR1::shared_ptr cpi_instance, saga::task (FuncBase::*async_func)(FuncRetV), RetVal ret) { return saga::run_wait (boost/*::phoenix*/::bind (async_func, cpi_instance, ret) ()); } /////////////////////////////////////////////////////////////////////////// // need async, have async // the application wants an asynchronous call, the adaptor provides a asynchronous // one. // so there is nothing to do, we have only to call the function. template inline saga::task async_async (TR1::shared_ptr cpi_instance, saga::task (FuncBase::*async_func)(FuncRetVal), RetVal ret) { return boost/*::phoenix*/::bind (async_func, cpi_instance, ret) (); } /////////////////////////////////////////////////////////////////////////// // dispatching to the appropriate functions // defined above. template inline saga::task dispatch_sync_async (run_mode mode, TR1::shared_ptr cpi_instance, void (FuncBase::*sync_func) (FuncRetVal), saga::task (FuncBase::*async_func) (FuncRetVal), char const * name, RetVal ret, bool (FuncBase::*prep_func)(FuncRetVal, saga::uuid) = NULL) { TR1::shared_ptr c = TR1::static_pointer_cast(cpi_instance); switch ( mode ) { case Sync_Sync: return sync_sync (c, sync_func, ret); case ASync_Sync: return async_sync (c, sync_func, ret, name, prep_func); case Sync_ASync: return sync_async (c, async_func, ret); case ASync_ASync: return async_async (c, async_func, ret); default: break; } // no adaptor found! SAGA_THROW_VERBATIM(cpi_instance.get(), std::string ("No adaptor implements method: ") + name, NoAdaptor); return saga::task(saga::task::Done); } /////////////////////////////////////////////////////////////////////// // This helper classes serves two purposes: // - it extracts and exposes the run_mode determined for the given adaptor // and the current CPI call // - it resets the adaptor pointer in the proxy<> class after the CPI // call whenever the adaptor has marked itself as Fixme. // struct run_mode_wrapper // { // typedef v1_0::preference_type preference_type; // typedef boost::recursive_mutex mutex_type; // // run_mode mode; // proxy * prx; // // run_mode_wrapper (proxy* p, char const* cpi, char const* name, // preference_type const& prefs, bool is_sync, // adaptor_selector::adaptor_info_list_type &no_no_list); // // ~run_mode_wrapper (void); // }; /////////////////////////////////////////////////////////////////////////// template inline saga::task execute_sync_async(proxy *prxy, char const *cpi_name, char const *name, char const *op_name, v1_0::preference_type const& prefs, bool is_sync, void (FuncBase::*sync_func)(FuncRetVal), saga::task (FuncBase::*async_func)(FuncRetVal), RetVal ret); /////////////////////////////////////////////////////////////////////////// // bring in higher order functions #include /////////////////////////////////////////////////////////////////////////////// }} // namespace saga::impl #endif // SAGA_IMPL_ENGINE_SYNC_ASYNC_HPP