Lunchbox  1.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lunchbox::SpinLock Class Reference

A fast lock for uncontended memory access. More...

#include <spinLock.h>

+ Inheritance diagram for lunchbox::SpinLock:
+ Collaboration diagram for lunchbox::SpinLock:

Public Member Functions

LUNCHBOX_API SpinLock ()
 Construct a new lock. More...
 
LUNCHBOX_API ~SpinLock ()
 Destruct the lock. More...
 
LUNCHBOX_API void set ()
 Acquire the lock exclusively. More...
 
LUNCHBOX_API void unset ()
 Release an exclusive lock. More...
 
LUNCHBOX_API bool trySet ()
 Attempt to acquire the lock exclusively. More...
 
LUNCHBOX_API void setRead ()
 Acquire the lock shared with other readers. More...
 
LUNCHBOX_API void unsetRead ()
 Release a shared read lock. More...
 
LUNCHBOX_API bool trySetRead ()
 Attempt to acquire the lock shared with other readers. More...
 
LUNCHBOX_API bool isSet ()
 Test if the lock is set. More...
 
LUNCHBOX_API bool isSetWrite ()
 Test if the lock is set exclusively. More...
 
LUNCHBOX_API bool isSetRead ()
 Test if the lock is set shared. More...
 

Detailed Description

A fast lock for uncontended memory access.

If Thread::yield() does not work, priority inversion is possible. If used as a read-write lock, readers or writers will starve on high contention.

See Also
ScopedMutex

Example:

/* Copyright (c) 2006-2014, Stefan Eilemann <eile@equalizergraphics.com>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 2.1 as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define TEST_RUNTIME 600 // seconds, needed for NighlyMemoryCheck
#include "test.h"
#include <lunchbox/atomic.h>
#include <lunchbox/clock.h>
#include <lunchbox/debug.h>
#include <lunchbox/init.h>
#include <lunchbox/lock.h>
#include <lunchbox/omp.h>
#include <lunchbox/spinLock.h>
#include <lunchbox/timedLock.h>
#include <iostream>
#define MAXTHREADS 256
#define TIME 500 // ms
bool _running = false;
template< class T > class Thread : public lunchbox::Thread
{
public:
Thread() : lock( 0 ), ops( 0 ) {}
T* lock;
size_t ops;
virtual void run()
{
ops = 0;
while( LB_LIKELY( _running ))
{
lock->set();
#ifndef _MSC_VER
TEST( lock->isSet( ));
#endif
lock->unset();
++ops;
}
}
};
template< class T > void _test()
{
T* lock = new T;
lock->set();
#ifdef LUNCHBOX_USE_OPENMP
const size_t nThreads = LB_MIN( lunchbox::OMP::getNThreads() * 3,
MAXTHREADS );
#else
const size_t nThreads = 16;
#endif
Thread< T > threads[MAXTHREADS];
for( size_t i = 1; i <= nThreads; i = i << 1 )
{
_running = true;
for( size_t j = 0; j < i; ++j )
{
threads[j].lock = lock;
TEST( threads[j].start( ));
}
lunchbox::sleep( 10 ); // let threads initialize
_clock.reset();
lock->unset();
lunchbox::sleep( TIME ); // let threads run
_running = false;
for( size_t j = 0; j < i; ++j )
TEST( threads[j].join( ));
const float time = _clock.getTimef();
TEST( !lock->isSet( ));
lock->set();
size_t ops = 0;
for( size_t j = 0; j < nThreads; ++j )
ops += threads[j].ops;
std::cout << std::setw(20) << lunchbox::className( lock ) << ", "
<< std::setw(12) << /*set, test, unset*/ 3 * ops / time
<< ", " << std::setw(3) << i << std::endl;
}
delete lock;
}
int main( int argc, char **argv )
{
TEST( lunchbox::init( argc, argv ));
std::cout << " Class, ops/ms, threads" << std::endl;
_test< lunchbox::SpinLock >();
std::cout << std::endl;
_test< lunchbox::Lock >();
std::cout << std::endl;
_test< lunchbox::TimedLock >();
TEST( lunchbox::exit( ));
return EXIT_SUCCESS;
}

Definition at line 38 of file spinLock.h.

Constructor & Destructor Documentation

LUNCHBOX_API lunchbox::SpinLock::SpinLock ( )

Construct a new lock.

Version
1.0
LUNCHBOX_API lunchbox::SpinLock::~SpinLock ( )

Destruct the lock.

Version
1.0

Member Function Documentation

LUNCHBOX_API bool lunchbox::SpinLock::isSet ( )

Test if the lock is set.

Returns
true if the lock is set, false if it is not set.
Version
1.0
LUNCHBOX_API bool lunchbox::SpinLock::isSetRead ( )

Test if the lock is set shared.

Returns
true if the lock is set, false if it is not set.
Version
1.1.2
LUNCHBOX_API bool lunchbox::SpinLock::isSetWrite ( )

Test if the lock is set exclusively.

Returns
true if the lock is set, false if it is not set.
Version
1.1.2
LUNCHBOX_API void lunchbox::SpinLock::set ( )

Acquire the lock exclusively.

Version
1.0
LUNCHBOX_API void lunchbox::SpinLock::setRead ( )

Acquire the lock shared with other readers.

Version
1.1.2
LUNCHBOX_API bool lunchbox::SpinLock::trySet ( )

Attempt to acquire the lock exclusively.

Returns
true if the lock was set, false if it was not set.
Version
1.0
LUNCHBOX_API bool lunchbox::SpinLock::trySetRead ( )

Attempt to acquire the lock shared with other readers.

Returns
true if the lock was set, false if it was not set.
Version
1.1.2
LUNCHBOX_API void lunchbox::SpinLock::unset ( )

Release an exclusive lock.

Version
1.0
LUNCHBOX_API void lunchbox::SpinLock::unsetRead ( )

Release a shared read lock.

Version
1.1.2

The documentation for this class was generated from the following file: