メインページ | モジュール | 名前空間一覧 | クラス階層 | 構成 | ファイル一覧 | 名前空間メンバ | 構成メンバ | ファイルメンバ | 関連ページ

toppers/sync.hpp

解説を見る。
00001 /*
00002  *  TOPPERS/C++ API Template Library
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      C++ API Template Library
00005  *
00006  *  Copyright (C) 2004 by TAKAGI Nobuhisa
00007  *
00008  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation
00009  *  によって公表されている GNU General Public License の Version 2 に記
00010  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
00011  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
00012  *  利用と呼ぶ)することを無償で許諾する.
00013  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00014  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00015  *      スコード中に含まれていること.
00016  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00017  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00018  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00019  *      の無保証規定を掲載すること.
00020  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00021  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00022  *      と.
00023  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00024  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00025  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00026  *        報告すること.
00027  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00028  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00029  *
00030  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00031  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
00032  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
00033  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
00034  *
00035  *  @(#) $Id: sync.hpp,v 1.1.1.1 2004/04/14 09:30:31 takagi-n Exp $
00036  */
00037 
00053 #ifndef TOPPERS_SYNC_HPP_
00054 #define TOPPERS_SYNC_HPP_
00055 
00056 #include <toppers/kernel.hpp>
00057 #include <toppers/assert.hpp>
00058 
00059 namespace toppers
00060 {
00061 
00062     namespace detail
00063     {
00064         template <bool SenseKernel, class LockObj> class lock_helper;
00065     }
00066 
00067     template <ID Id, class Diagnostics, class Stub> class semaphore;
00068     template <ID Id, class Diagnostics, class Stub> class mutex;
00069 
00090     template <class LockObj, bool SenseKernel = false>
00091     class lock
00092     {
00093         LockObj lock_;
00094 
00095     public:
00097         lock()
00098         {
00099             detail::lock_helper<SenseKernel, LockObj>::lock(lock_);
00100         }
00102         template <typename T>
00103         explicit lock(T arg)
00104             : lock_(arg)
00105         {
00106             detail::lock_helper<SenseKernel, LockObj>::lock(lock_);
00107         }
00109         ~lock() throw()
00110         {
00111             detail::lock_helper<SenseKernel, LockObj>::unlock(lock_);
00112         }
00113     };
00114 
00115     template <bool SenseKernel>
00116     class lock<void, SenseKernel>
00117     {
00118         lock()
00119         {
00120         }
00121         template <typename T>
00122         explicit lock(T arg)
00123         {
00124         }
00125     };
00126 
00148     template <class LockObj, bool SenseKernel = false>
00149     class recursive_lock
00150     {
00151         bool state_;
00152         LockObj lock_;
00153 
00154     public:
00156         recursive_lock()
00157         {
00158             state_ = detail::lock_helper<SenseKernel, LockObj>::sense(lock_);
00159             if (!state_)
00160                 detail::lock_helper<SenseKernel, LockObj>::lock(lock_);
00161         }
00163         template <typename T>
00164         explicit recursive_lock(T arg)
00165             : lock_(arg)
00166         {
00167             state_ = detail::lock_helper<SenseKernel, LockObj>::sense(lock_);
00168             if (!state_)
00169                 detail::lock_helper<SenseKernel, LockObj>::lock(lock_);
00170         }
00172         ~recursive_lock() throw()
00173         {
00174             if (!state_)
00175                 detail::lock_helper<SenseKernel, LockObj>::unlock(lock_);
00176         }
00177     };
00178 
00179     template <bool SenseKernel>
00180     class recursive_lock<void, SenseKernel>
00181     {
00182         recursive_lock()
00183         {
00184         }
00185         template <typename T>
00186         explicit recursive_lock(T arg)
00187         {
00188         }
00189     };
00190 
00191     namespace detail
00192     {
00193 
00194         template <class LockObj, ID Id, class Stub, bool SenseKernel>
00195         class recursive_lock_helper
00196         {
00197             TOPPERS_STATIC_ASSERT(Id > 0);
00198             LockObj lock_;
00199             static ID   holder_;
00200             static UINT counter_;
00201 
00202         public:
00203             recursive_lock_helper()
00204             {
00205                 if (!sense_kernel<SenseKernel>() && !Stub::stub_sns_dsp())
00206                 {
00207                     ID tskid;
00208                     Stub::stub_get_tid(&tskid);
00209                     if (holder_ != tskid)
00210                     {
00211                         detail::lock_helper<false, LockObj>::lock(lock_);
00212                         holder_ = tskid;
00213                     }
00214                     ++counter_;
00215                 }
00216             }
00217             ~recursive_lock_helper() throw()
00218             {
00219                 if (!sense_kernel<SenseKernel>() && !Stub::stub_sns_dsp())
00220                 {
00221                     if (--counter_ == 0)
00222                     {
00223                         holder_ = 0;
00224                         detail::lock_helper<false, LockObj>::unlock(lock_);
00225                     }
00226                 }
00227             }
00228         };
00229 
00230         template <class LockObj, ID Id, class Stub, bool SenseKernel>
00231         ID  recursive_lock_helper<LockObj, Id, Stub, SenseKernel>::holder_ = 0;
00232 
00233         template <class LockObj, ID Id, class Stub, bool SenseKernel>
00234         UINT    recursive_lock_helper<LockObj, Id, Stub, SenseKernel>::counter_ = 0;
00235 
00236     }
00237 
00238     template <ID Id, class Diagnostics, class Stub, bool SenseKernel>
00239     class recursive_lock<semaphore<Id, Diagnostics, Stub>, SenseKernel>
00240         : detail::recursive_lock_helper<semaphore<Id, Diagnostics, Stub>, Id, Stub, SenseKernel>
00241     {
00242     };
00243 
00244     template <ID Id, class Diagnostics, class Stub, bool SenseKernel>
00245     class recursive_lock<mutex<Id, Diagnostics, Stub>, SenseKernel>
00246         : detail::recursive_lock_helper<mutex<Id, Diagnostics, Stub>, Id, Stub, SenseKernel>
00247     {
00248     };
00249 
00264     template <class LockObj, typename T>
00265     inline T& sync_increment(T& x)
00266     {
00267         lock<LockObj> loc;
00268         return ++x;
00269     }
00270 
00285     template <class LockObj, typename T>
00286     inline T& sync_decrement(T& x)
00287     {
00288         lock<LockObj> loc;
00289         return --x;
00290     }
00291 
00307     template <class LockObj, typename T>
00308     inline void sync_swap(T& x, T& y)
00309     {
00310         lock<LockObj> loc;
00311         T t = x;
00312         x = y;
00313         y = t;
00314     }
00315 
00316 }
00317 
00318 #endif  // ! TOPPERS_SYNC_HPP_