libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/io/async_base.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2011 Juan Pedro BolĂ­var Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 #ifndef PSYNTH_IO_ASYNC_BASE_H_
00032 #define PSYNTH_IO_ASYNC_BASE_H_
00033 
00034 #include <functional>
00035 #include <atomic>
00036 
00037 #include <psynth/io/exception.hpp>
00038 
00039 namespace psynth
00040 {
00041 namespace io
00042 {
00043 
00044 PSYNTH_DECLARE_ERROR (error, async_error);
00045 PSYNTH_DECLARE_ERROR (async_error, async_not_running_error);
00046 PSYNTH_DECLARE_ERROR (async_error, async_not_idle_error);
00047 
00048 enum class async_state : int
00049 {
00050     idle,
00051     running
00052 };
00053 
00054 class async_base
00055 {
00056 public:
00057     typedef std::function<void (std::size_t)> callback_type;
00058     
00059     virtual ~async_base () {}
00060     
00061     virtual void start () = 0;
00062     virtual void stop () = 0;
00063     virtual async_state state () const = 0;
00064     virtual void set_callback (callback_type cb) = 0;
00065     
00066     void soft_start ()
00067     {
00068         if (state () == async_state::idle)
00069             start ();
00070     }
00071     
00072     void soft_stop ()
00073     {
00074         if (state () == async_state::running)
00075             stop ();
00076     }
00077 
00078     void check_running ()
00079     {
00080         if (state () != async_state::running)
00081             throw async_not_running_error ();
00082     }
00083 
00084     void check_idle ()
00085     {
00086         if (state () != async_state::idle)
00087             throw async_not_idle_error ();
00088     }
00089 };
00090 
00091 namespace detail
00092 {
00093 
00099 class async_base_impl : public virtual async_base
00100 {
00101 public:
00102     typedef std::function<void (std::size_t)> callback_type;
00103 
00104     async_base_impl (callback_type cb = callback_type ())
00105         : _state ((int) async_state::idle)
00106         , _callback (cb)
00107     {
00108     }
00109     
00110     virtual ~async_base_impl () {}
00111     
00112     async_state state () const
00113     { return (async_state) (int) _state; }
00114     
00115     void set_callback (callback_type cb)
00116     {
00117         check_idle ();
00118         _callback = cb;
00119     }
00120     
00121 protected:
00122     void set_state (async_state state)
00123     { _state = (int) state; }
00124 
00125     void process (std::size_t nframes)
00126     { _callback (nframes); }
00127     
00128 private:
00129     std::atomic<int> _state; // FIXME: Why does GCC does not support
00130                              // this with an enum?
00131     callback_type    _callback;
00132 };
00133 
00134 };
00135 
00136 } /* namespace io */
00137 } /* namespace psynth */
00138 
00139 #endif /* PSYNTH_IO_ASYNC_BASE_H_ */