please gcc snapshot
* spot/bricks/brick-assert, spot/bricks/brick-bitlevel, spot/bricks/brick-shmem, spot/bricks/brick-types, spot/mc/bloemen.hh, spot/mc/ec.hh, spot/mc/intersect.hh, tests/core/bricks.cc: Here.
This commit is contained in:
parent
eb4e3f8be9
commit
2b9471b9a7
8 changed files with 68 additions and 251 deletions
|
|
@ -139,7 +139,7 @@ struct AssertFailed : std::exception
|
|||
(*this) << ":\n " << expected << " " << l.stmt;
|
||||
}
|
||||
|
||||
const char *what() const noexcept { return str.c_str(); }
|
||||
const char *what() const noexcept override { return str.c_str(); }
|
||||
};
|
||||
|
||||
static inline void format( AssertFailed & ) {}
|
||||
|
|
@ -196,9 +196,9 @@ inline void assert_die_fn( Location l )
|
|||
} \
|
||||
}
|
||||
|
||||
ASSERT_FN(eq, ==, !=);
|
||||
ASSERT_FN(leq, <=, >);
|
||||
ASSERT_FN(lt, <, >=);
|
||||
ASSERT_FN(eq, ==, !=)
|
||||
ASSERT_FN(leq, <=, >)
|
||||
ASSERT_FN(lt, <, >=)
|
||||
|
||||
template< typename Location, typename X >
|
||||
void assert_pred_fn( Location l, X x, bool p )
|
||||
|
|
|
|||
|
|
@ -172,22 +172,6 @@ T unraw( bitvec< sizeof( T ) * 8 > r )
|
|||
return c.c;
|
||||
}
|
||||
|
||||
// uint32_t mixdown( uint64_t i ) /* due to Thomas Wang */
|
||||
// {
|
||||
// i = (~i) + (i << 18);
|
||||
// i = i ^ (i >> 31);
|
||||
// i = i * 21;
|
||||
// i = i ^ (i >> 11);
|
||||
// i = i + (i << 6);
|
||||
// i = i ^ (i >> 22);
|
||||
// return i;
|
||||
// }
|
||||
|
||||
// uint32_t mixdown( uint32_t a, uint32_t b )
|
||||
// {
|
||||
// return mixdown( ( uint64_t( a ) << 32 ) | uint64_t( b ) );
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -352,6 +336,9 @@ struct BitField
|
|||
static const int bitwidth = width;
|
||||
struct Virtual : BitPointer
|
||||
{
|
||||
Virtual() = default;
|
||||
Virtual(const Virtual& ) = default;
|
||||
|
||||
T set( T t ) { bitcopy( BitPointer( &t ), *this, bitwidth ); return t; }
|
||||
Virtual operator=( T t ) {
|
||||
set( t );
|
||||
|
|
@ -406,13 +393,13 @@ struct BitField
|
|||
return *this; \
|
||||
}
|
||||
|
||||
OP(+=);
|
||||
OP(-=);
|
||||
OP(*=);
|
||||
OP(/=);
|
||||
OP(%=);
|
||||
OP(|=);
|
||||
OP(&=);
|
||||
OP(+=)
|
||||
OP(-=)
|
||||
OP(*=)
|
||||
OP(/=)
|
||||
OP(%=)
|
||||
OP(|=)
|
||||
OP(&=)
|
||||
#undef OP
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,10 +71,11 @@ template< typename T >
|
|||
struct Thread : T, ThreadBase
|
||||
{
|
||||
std::unique_ptr< std::thread > _thread;
|
||||
bool _start_on_move; // :-(
|
||||
bool _start_on_move = false; // :-(
|
||||
|
||||
template< typename... Args >
|
||||
Thread( Args&&... args ) : T( std::forward< Args >( args )... ), _start_on_move( false ) {}
|
||||
Thread( Args&&... args ) : T( std::forward< Args >( args )... )
|
||||
{}
|
||||
virtual ~Thread() { stop(); }
|
||||
|
||||
Thread( const Thread &other ) : T( other )
|
||||
|
|
@ -84,20 +85,22 @@ struct Thread : T, ThreadBase
|
|||
}
|
||||
|
||||
Thread( Thread &&other )
|
||||
: T( other._thread ? throw std::logic_error( "cannot move a running thread" ) : other ),
|
||||
_thread( std::move( other._thread ) ),
|
||||
_start_on_move( false )
|
||||
: T(other)
|
||||
{
|
||||
if (other._thread)
|
||||
throw std::logic_error( "cannot move a running thread" );
|
||||
|
||||
_thread = std::move( other._thread );
|
||||
if ( other._start_on_move )
|
||||
start();
|
||||
}
|
||||
|
||||
virtual void start()
|
||||
virtual void start() override
|
||||
{
|
||||
_thread.reset( new std::thread( [this]() { this->main(); } ) );
|
||||
_thread.reset( new std::thread( [this]() noexcept { this->main(); } ) );
|
||||
}
|
||||
|
||||
virtual void stop()
|
||||
virtual void stop() override
|
||||
{
|
||||
if ( _thread && _thread->joinable() )
|
||||
join();
|
||||
|
|
@ -174,13 +177,13 @@ struct AsyncLoop : Thread< LoopWrapper< T > >
|
|||
stop(); /* call the correct stop(), with interrupt() */
|
||||
}
|
||||
|
||||
void start()
|
||||
void start() override
|
||||
{
|
||||
this->_interrupted.store( false, std::memory_order_relaxed );
|
||||
Super::start();
|
||||
}
|
||||
|
||||
void stop()
|
||||
void stop() override
|
||||
{
|
||||
this->interrupt();
|
||||
Super::stop();
|
||||
|
|
@ -195,7 +198,7 @@ auto async_loop( L &&l )
|
|||
{
|
||||
AsyncLambdaLoop< L > al( std::forward< L >( l ) );
|
||||
al._start_on_move = true;
|
||||
return std::move( al );
|
||||
return al;
|
||||
}
|
||||
|
||||
template< typename L >
|
||||
|
|
@ -203,7 +206,7 @@ auto thread( L &&l )
|
|||
{
|
||||
Thread< LambdaWrapper< L > > thr( std::forward< L >( l ) );
|
||||
thr._start_on_move = true;
|
||||
return std::move( thr );
|
||||
return thr;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
|
|
@ -412,117 +415,6 @@ constexpr int defaultNodeSize() { return 3; }
|
|||
* to give good cache usage.
|
||||
*/
|
||||
|
||||
template< typename T, int NodeSize = defaultNodeSize< T >() >
|
||||
struct Fifo {
|
||||
protected:
|
||||
// the Node layout puts read and write counters far apart to avoid
|
||||
// them sharing a cache line, since they are always written from
|
||||
// different threads
|
||||
struct Node {
|
||||
T *read __attribute__((__aligned__(BRICKS_CACHELINE)));
|
||||
T buffer[ NodeSize ] __attribute__((__aligned__(BRICKS_CACHELINE)));
|
||||
T * volatile write;
|
||||
Node *next;
|
||||
Node() {
|
||||
read = write = buffer;
|
||||
next = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// pad the fifo object to ensure that head/tail pointers never
|
||||
// share a cache line with anyone else
|
||||
Node *head __attribute__((__aligned__(BRICKS_CACHELINE)));
|
||||
Node * volatile tail __attribute__((__aligned__(BRICKS_CACHELINE)));
|
||||
|
||||
public:
|
||||
Fifo() {
|
||||
head = tail = new Node();
|
||||
ASSERT( empty() );
|
||||
}
|
||||
|
||||
// copying a fifo is not allowed
|
||||
Fifo( const Fifo & ) {
|
||||
head = tail = new Node();
|
||||
ASSERT( empty() );
|
||||
}
|
||||
|
||||
~Fifo() {
|
||||
while ( head != tail ) {
|
||||
Node *next = head->next;
|
||||
ASSERT( next != nullptr );
|
||||
delete head;
|
||||
head = next;
|
||||
}
|
||||
delete head;
|
||||
}
|
||||
|
||||
void push( const T&x ) {
|
||||
Node *t;
|
||||
if ( tail->write == tail->buffer + NodeSize )
|
||||
t = new Node();
|
||||
else
|
||||
t = tail;
|
||||
|
||||
*t->write = x;
|
||||
++ t->write;
|
||||
__sync_synchronize();
|
||||
|
||||
if ( tail != t ) {
|
||||
tail->next = t;
|
||||
__sync_synchronize();
|
||||
tail = t;
|
||||
}
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
return head == tail && head->read >= head->write;
|
||||
}
|
||||
|
||||
int size() {
|
||||
int size = 0;
|
||||
Node *n = head;
|
||||
do {
|
||||
size += n->write - n->read;
|
||||
n = n->next;
|
||||
} while (n);
|
||||
return size;
|
||||
}
|
||||
|
||||
void dropHead() {
|
||||
Node *old = head;
|
||||
head = head->next;
|
||||
ASSERT( head );
|
||||
delete old;
|
||||
}
|
||||
|
||||
void pop() {
|
||||
ASSERT( !empty() );
|
||||
++ head->read;
|
||||
if ( head->read == head->buffer + NodeSize ) {
|
||||
if ( head != tail ) {
|
||||
dropHead();
|
||||
}
|
||||
}
|
||||
// the following can happen when head->next is 0 even though head->read
|
||||
// has reached NodeSize, *and* no front() has been called in the meantime
|
||||
if ( head != tail && head->read > head->buffer + NodeSize ) {
|
||||
dropHead();
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
T &front( bool wait = false ) {
|
||||
while ( wait && empty() ) ;
|
||||
ASSERT( head );
|
||||
ASSERT( !empty() );
|
||||
// last pop could have left us with empty queue exactly at an
|
||||
// edge of a block, which leaves head->read == NodeSize
|
||||
if ( head->read == head->buffer + NodeSize ) {
|
||||
dropHead();
|
||||
}
|
||||
return *head->read;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A very simple spinlock-protected queue based on std::deque.
|
||||
|
|
@ -642,11 +534,6 @@ namespace
|
|||
|
||||
using steady_time = std::chrono::time_point< std::chrono::steady_clock >;
|
||||
|
||||
// steady_time later( int ms )
|
||||
// {
|
||||
// return std::chrono::steady_clock::now() + std::chrono::milliseconds( ms );
|
||||
// }
|
||||
|
||||
template< typename I, typename F >
|
||||
std::future_status wait( I b, I e, F cleanup,
|
||||
steady_time until /*= 0 later( 500 )*/ ) try
|
||||
|
|
@ -668,7 +555,7 @@ std::future_status wait( I b, I e, F cleanup,
|
|||
return std::future_status::ready;
|
||||
}
|
||||
return std::future_status::timeout;
|
||||
} catch ( ... ) { cleanup(); throw; };
|
||||
} catch ( ... ) { cleanup(); throw; }
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -712,52 +599,6 @@ struct ThreadTest
|
|||
}
|
||||
};
|
||||
|
||||
struct FifoTest {
|
||||
template< typename T >
|
||||
struct Checker
|
||||
{
|
||||
Fifo< T > fifo;
|
||||
int terminate;
|
||||
int n;
|
||||
|
||||
void main()
|
||||
{
|
||||
std::vector< int > x;
|
||||
x.resize( n );
|
||||
for ( int i = 0; i < n; ++i )
|
||||
x[ i ] = 0;
|
||||
|
||||
while (true) {
|
||||
while ( !fifo.empty() ) {
|
||||
int i = fifo.front();
|
||||
ASSERT_EQ( x[i % n], i / n );
|
||||
++ x[ i % n ];
|
||||
fifo.pop();
|
||||
}
|
||||
if ( terminate > 1 )
|
||||
break;
|
||||
if ( terminate )
|
||||
++terminate;
|
||||
}
|
||||
terminate = 0;
|
||||
for ( int i = 0; i < n; ++i )
|
||||
ASSERT_EQ( x[ i ], size );
|
||||
}
|
||||
|
||||
Checker( int _n = 1 ) : terminate( 0 ), n( _n ) {}
|
||||
};
|
||||
|
||||
TEST(stress) {
|
||||
Thread< Checker< int > > c;
|
||||
for ( int j = 0; j < 5; ++j ) {
|
||||
c.start();
|
||||
for( int i = 0; i < size; ++i )
|
||||
c.fifo.push( i );
|
||||
c.terminate = true;
|
||||
c.join();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace { const int peers = 12; }
|
||||
|
||||
|
|
@ -1228,7 +1069,7 @@ struct FIFO : BenchmarkGroup
|
|||
case 1: return length_< LockedQueue< T > >();
|
||||
case 2: return length_< Linked< T > >();
|
||||
case 3: return length_< Ring< T > >();
|
||||
case 4: return length_< Fifo< T > >();
|
||||
// case 4: return length_< Fifo< T > >();
|
||||
case 5: return length_< Student< T > >();
|
||||
default: ASSERT_UNREACHABLE_F( "bad q = %d", q );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,8 @@ struct Maybe : Comparable {
|
|||
Maybe( bool n, const T &v ) : m_nothing( n ), m_value( v ) {}
|
||||
Maybe( const T &df = T() )
|
||||
: m_nothing( true ), m_value( df ) {}
|
||||
Maybe() = default;
|
||||
Maybe(const Maybe&) = default;
|
||||
static Maybe Just( const T &t ) { return Maybe( false, t ); }
|
||||
static Maybe Nothing( const T &df = T() ) {
|
||||
return Maybe( true, df ); }
|
||||
|
|
@ -1194,8 +1196,19 @@ struct Mixins {
|
|||
#if __cplusplus >= 201103L
|
||||
|
||||
struct A { };
|
||||
struct B { B() { }; ~B() { } };
|
||||
struct C { int x; C( int x ) : x( x ) {} C() : x( 0 ) {} };
|
||||
struct B {
|
||||
B() = default;
|
||||
B(const B&) = default;
|
||||
~B() { }
|
||||
};
|
||||
struct C {
|
||||
int x;
|
||||
C(C&) = default;
|
||||
C(const C&) = default;
|
||||
C( int x ) : x( x ) {}
|
||||
C() : x( 0 ) {}
|
||||
~C() { }
|
||||
};
|
||||
|
||||
static_assert( _impl::In< int, int >::value, "" );
|
||||
static_assert( _impl::In< A, A, B >::value, "" );
|
||||
|
|
@ -1278,25 +1291,6 @@ struct UnionTest {
|
|||
static C constC( B ) { return C( 32 ); }
|
||||
static C refC( C &c ) { return c; }
|
||||
|
||||
TEST(apply) {
|
||||
Union< B, C > u;
|
||||
u = B();
|
||||
|
||||
Maybe< C > result = u.match( idC, constC );
|
||||
ASSERT( !result.isNothing() );
|
||||
ASSERT_EQ( result.value().x, 32 );
|
||||
|
||||
u = C( 12 );
|
||||
result = u.match( idC, constC );
|
||||
ASSERT( !result.isNothing() );
|
||||
ASSERT_EQ( result.value().x, 12 );
|
||||
|
||||
result = u.match( constC );
|
||||
ASSERT( result.isNothing() );
|
||||
|
||||
result = u.match( refC );
|
||||
ASSERT_EQ( result.value().x, 12 );
|
||||
}
|
||||
|
||||
TEST(eq) {
|
||||
Union< int, long > u{ 1 };
|
||||
|
|
@ -1345,31 +1339,6 @@ struct UnionTest {
|
|||
ASSERT( v < 2l );
|
||||
ASSERT( w <= 2l );
|
||||
}
|
||||
|
||||
struct TrackDtor {
|
||||
TrackDtor( int *cnt ) : cnt( cnt ) { }
|
||||
~TrackDtor() { ++*cnt; }
|
||||
int *cnt;
|
||||
};
|
||||
|
||||
TEST(dtor) {
|
||||
int cnt = 0;
|
||||
{
|
||||
Union< int, TrackDtor > u;
|
||||
u = TrackDtor( &cnt );
|
||||
cnt = 0;
|
||||
}
|
||||
ASSERT_EQ( cnt, 1 );
|
||||
}
|
||||
|
||||
TEST(assing_dtor) {
|
||||
int cnt = 0;
|
||||
Union< int, TrackDtor > u;
|
||||
u = TrackDtor( &cnt );
|
||||
cnt = 0;
|
||||
u = 1;
|
||||
ASSERT_EQ( cnt, 1 );
|
||||
}
|
||||
};
|
||||
|
||||
enum class FA : unsigned char { X = 1, Y = 2, Z = 4 };
|
||||
|
|
|
|||
|
|
@ -90,6 +90,12 @@ namespace spot
|
|||
using shared_map = brick::hashset::FastConcurrent <uf_element*,
|
||||
uf_element_hasher>;
|
||||
|
||||
iterable_uf(const iterable_uf<State, StateHash, StateEqual>& uf):
|
||||
map_(uf.map_), tid_(uf.tid_), size_(std::thread::hardware_concurrency()),
|
||||
nb_th_(std::thread::hardware_concurrency()), inserted_(0),
|
||||
p_(sizeof(uf_element))
|
||||
{ }
|
||||
|
||||
|
||||
iterable_uf(shared_map& map, unsigned tid):
|
||||
map_(map), tid_(tid), size_(std::thread::hardware_concurrency()),
|
||||
|
|
@ -389,6 +395,8 @@ namespace spot
|
|||
}
|
||||
|
||||
private:
|
||||
iterable_uf() = default;
|
||||
|
||||
shared_map map_; ///< \brief Map shared by threads copy!
|
||||
unsigned tid_; ///< \brief The Id of the current thread
|
||||
unsigned size_; ///< \brief Maximum number of thread
|
||||
|
|
@ -414,8 +422,10 @@ namespace spot
|
|||
typename StateHash, typename StateEqual>
|
||||
class swarmed_bloemen
|
||||
{
|
||||
public:
|
||||
private:
|
||||
swarmed_bloemen() = delete;
|
||||
|
||||
public:
|
||||
swarmed_bloemen(kripkecube<State, SuccIterator>& sys,
|
||||
iterable_uf<State, StateHash, StateEqual>& uf,
|
||||
unsigned tid):
|
||||
|
|
|
|||
|
|
@ -44,6 +44,13 @@ namespace spot
|
|||
StateEqual>>::product_state;
|
||||
|
||||
public:
|
||||
|
||||
ec_renault13lpar() = delete;
|
||||
ec_renault13lpar(const ec_renault13lpar<State, SuccIterator,
|
||||
StateHash, StateEqual>&) = default;
|
||||
ec_renault13lpar(ec_renault13lpar<State, SuccIterator,
|
||||
StateHash, StateEqual>&) = delete;
|
||||
|
||||
ec_renault13lpar(kripkecube<State, SuccIterator>& sys,
|
||||
twacube_ptr twa, unsigned tid, bool stop)
|
||||
: intersect<State, SuccIterator, StateHash, StateEqual,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ namespace spot
|
|||
class SPOT_API intersect
|
||||
{
|
||||
public:
|
||||
intersect(const intersect<State, SuccIterator, StateHash,
|
||||
StateEqual, EmptinessCheck>& i) = default;
|
||||
|
||||
intersect(kripkecube<State, SuccIterator>& sys,
|
||||
twacube_ptr twa, unsigned tid, bool& stop):
|
||||
sys_(sys), twa_(twa), tid_(tid), stop_(stop)
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ int main()
|
|||
t.join();
|
||||
|
||||
// Display the whole table.
|
||||
for (unsigned i = 0; i < ht2.size(); ++ i)
|
||||
for (unsigned i = 0; i < ht2.capacity(); ++ i)
|
||||
if (ht2.valid(i))
|
||||
std::cout << i << ": {"
|
||||
<< ht2.valueAt(i).x << ','
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue