Home / Open source / Gate
Gate portable class
This is example how to create more complicated synchronization object - gate
/*
* The Software License
* ====================================================================
* Copyright (c) 2003 The Terimber Corporation. All rights
* reserved.
* ====================================================================
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE TERIMBER CORPORATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*/
// Header file starts here.
// gate.h
#ifndef _terimber_gate_h_
#define _terimber_gate_h_
#include "thread.h"
// class supports free-thread restrict source access
// there are two sides: server (1) and clients (N)
//
class gate
{
// prevent copy objects
gate(const gate& src);
gate& operator=(const gate& src);
public:
//
// constructor
//
gate(size_t max_count);
//
// client calls when start using resource
//
bool entry(size_t timeout = INFINITE) const;
//
// client calls when finish using resource
//
void leave() const;
//
// server call to prevent entries of new clients
// and wait untill all clients will leave resource
//
bool lock(size_t timeout = INFINITE) const;
//
// allows new client to come
//
void unlock() const;
private:
semaphore _sema; // semaphore
size_t _max_count; // max visitors
};
// automatic gate keeper for server side
class gate_keeper
{
public:
//
// constructor
//
gate_keeper(const gate& gate_, size_t timeout = INFINITE) : _gate(gate_)
{ _locked = _gate.lock(timeout); }
//
// destructor
//
~gate_keeper()
{ if (_locked) _gate.unlock(); }
//
// check the locked state
//
inline operator bool() const { return _locked; }
inline bool operator!() const { return !_locked; }
private:
bool _locked; // flag that gate was locked
const gate& _gate; // gate
};
// class supports automatic entry/leave of gate for the clients
class gate_client
{
public:
//
// constructor
//
gate_client(const gate& gate_, size_t timeout = INFINITE) : _gate(gate_)
{ _inside = _gate.entry(timeout); }
//
// destructor
//
~gate_client()
{ if (_inside) _gate.leave(); }
// check access flag
inline operator bool() const { return _inside; }
inline bool operator!() const { return !_inside; }
private:
bool _inside; // flag that client was allowed to enter to the gate
const gate& _gate; // gate
};
// Source file begins
// gate.cpp
#include "gate.h"
gate::gate(size_t max_count) :
_sema(max_count, max_count),
_max_count(max_count)
{
}
// client calls when start using resource
bool
gate::entry(size_t timeout) const
{
return WAIT_OBJECT_0 == _sema.wait(timeout);
}
// client calls when finish using resource
void
gate::leave() const
{
_sema.release();
}
// server call to prevent entries of new clients
// and wait untill all clients will leave resource
bool
gate::lock(size_t timeout) const
{
size_t count = 0;
for (; count < _max_count && WAIT_OBJECT_0 == _sema.wait(timeout); ++count);
return count == _max_count;
}
// free resource for client entries
void
gate::unlock() const
{
_sema.release(_max_count);
}
|
|