mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 12:56:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			526 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			526 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
						|
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
 | 
						|
/* -*- mode: C; c-basic-offset: 4 -*- */
 | 
						|
#ident "$Id$"
 | 
						|
/*======
 | 
						|
This file is part of TokuDB
 | 
						|
 | 
						|
 | 
						|
Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
 | 
						|
 | 
						|
    TokuDBis is free software: you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU General Public License, version 2,
 | 
						|
    as published by the Free Software Foundation.
 | 
						|
 | 
						|
    TokuDB 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 General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with TokuDB.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
======= */
 | 
						|
 | 
						|
#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
 | 
						|
 | 
						|
#ifndef _TOKUDB_SYNC_H
 | 
						|
#define _TOKUDB_SYNC_H
 | 
						|
 | 
						|
#include "hatoku_defines.h"
 | 
						|
#include "tokudb_debug.h"
 | 
						|
#include "tokudb_time.h"
 | 
						|
 | 
						|
namespace tokudb {
 | 
						|
namespace thread {
 | 
						|
 | 
						|
extern const pfs_key_t pfs_not_instrumented;
 | 
						|
 | 
						|
uint my_tid(void);
 | 
						|
 | 
						|
// Your basic mutex
 | 
						|
class mutex_t {
 | 
						|
public:
 | 
						|
    explicit mutex_t(pfs_key_t key);
 | 
						|
    mutex_t(void) : mutex_t(pfs_not_instrumented) {}
 | 
						|
    ~mutex_t(void);
 | 
						|
 | 
						|
    void reinit(pfs_key_t key);
 | 
						|
    void lock(
 | 
						|
#if defined(SAFE_MUTEX) || defined(HAVE_PSI_MUTEX_INTERFACE)
 | 
						|
        const char* src_file,
 | 
						|
        uint src_line
 | 
						|
#endif  // SAFE_MUTEX || HAVE_PSI_MUTEX_INTERFACE
 | 
						|
        );
 | 
						|
    void unlock(
 | 
						|
#if defined(SAFE_MUTEX)
 | 
						|
        const char* src_file,
 | 
						|
        uint src_line
 | 
						|
#endif  // SAFE_MUTEX
 | 
						|
        );
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
    bool is_owned_by_me(void) const;
 | 
						|
#endif
 | 
						|
private:
 | 
						|
    static pthread_t _null_owner;
 | 
						|
    mysql_mutex_t _mutex;
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
    uint _owners;
 | 
						|
    pthread_t _owner;
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
// Simple read write lock
 | 
						|
class rwlock_t {
 | 
						|
public:
 | 
						|
    explicit rwlock_t(pfs_key_t key);
 | 
						|
    rwlock_t(void) : rwlock_t(pfs_not_instrumented) {}
 | 
						|
    ~rwlock_t(void);
 | 
						|
 | 
						|
    void lock_read(
 | 
						|
#ifdef HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
        const char* src_file,
 | 
						|
        uint src_line
 | 
						|
#endif  // HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
        );
 | 
						|
    void lock_write(
 | 
						|
#ifdef HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
        const char* src_file,
 | 
						|
        uint src_line
 | 
						|
#endif  // HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
        );
 | 
						|
    void unlock(void);
 | 
						|
 | 
						|
private:
 | 
						|
    rwlock_t(const rwlock_t&);
 | 
						|
    rwlock_t& operator=(const rwlock_t&);
 | 
						|
 | 
						|
    mysql_rwlock_t _rwlock;
 | 
						|
};
 | 
						|
 | 
						|
// Simple event signal/wait class
 | 
						|
class event_t {
 | 
						|
public:
 | 
						|
    // create_signalled - create the event in a signalled state
 | 
						|
    // manual_reset - create an event that must be manually reset
 | 
						|
    // after signaling
 | 
						|
    event_t(
 | 
						|
        bool create_signalled = false,
 | 
						|
        bool manual_reset = false);
 | 
						|
    ~event_t(void);
 | 
						|
 | 
						|
    // wait for the event to become signalled
 | 
						|
    void wait(void);
 | 
						|
 | 
						|
    // signal the event
 | 
						|
    void signal(void);
 | 
						|
 | 
						|
    // pulse the event (signal and free exactly one waiter)
 | 
						|
    void pulse(void);
 | 
						|
 | 
						|
    // is the event currently signalled
 | 
						|
    bool signalled(void);
 | 
						|
 | 
						|
    // unsignal/clear the event
 | 
						|
    void reset(void);
 | 
						|
 | 
						|
private:
 | 
						|
    event_t(const event_t&);
 | 
						|
    event_t& operator=(const event_t&);
 | 
						|
 | 
						|
    pthread_mutex_t		_mutex;
 | 
						|
    pthread_cond_t		_cond;
 | 
						|
    bool			_signalled;
 | 
						|
    bool			_pulsed;
 | 
						|
    bool			_manual_reset;
 | 
						|
};
 | 
						|
 | 
						|
// Semaphore signal/wait class
 | 
						|
class semaphore_t {
 | 
						|
public:
 | 
						|
    // initial_count - the initial signal count of the semaphore
 | 
						|
    // max_count - the maximum signal count for the semaphore.
 | 
						|
    semaphore_t(int initial_count, int max_count);
 | 
						|
    ~semaphore_t(void);
 | 
						|
 | 
						|
    enum E_WAIT {
 | 
						|
        E_SIGNALLED = 0,
 | 
						|
        E_INTERRUPTED = 1,
 | 
						|
        E_TIMEDOUT = 2
 | 
						|
    };
 | 
						|
 | 
						|
    // wait for the semaphore to become signalled
 | 
						|
    E_WAIT wait(void);
 | 
						|
 | 
						|
    // signal the semaphore to increase the count
 | 
						|
    // return true if signalled, false if ignored due to count
 | 
						|
    bool signal(void);
 | 
						|
 | 
						|
    // what is the semaphore signal count
 | 
						|
    int signalled(void);
 | 
						|
 | 
						|
    // unsignal a signalled semaphore
 | 
						|
    void reset(void);
 | 
						|
 | 
						|
    // set to interrupt any waiters, as long as is set,
 | 
						|
    // waiters will return immediately with E_INTERRUPTED.
 | 
						|
    // the semaphore signal count and tracking will continue
 | 
						|
    // accepting signals and leave the signalled state intact
 | 
						|
    void set_interrupt(void);
 | 
						|
    void clear_interrupt(void);
 | 
						|
 | 
						|
private:
 | 
						|
    semaphore_t(const semaphore_t&);
 | 
						|
    semaphore_t& operator=(const semaphore_t&);
 | 
						|
 | 
						|
    pthread_mutex_t		_mutex;
 | 
						|
    pthread_cond_t		_cond;
 | 
						|
    bool			_interrupted;
 | 
						|
    int			_signalled;
 | 
						|
    int			_initial_count;
 | 
						|
    int			_max_count;
 | 
						|
};
 | 
						|
 | 
						|
// Thread class
 | 
						|
class thread_t {
 | 
						|
public:
 | 
						|
    thread_t(void);
 | 
						|
    ~thread_t(void);
 | 
						|
 | 
						|
    int start(void* (*pfn)(void*), void* arg);
 | 
						|
    int join(void** value_ptr);
 | 
						|
    int detach(void);
 | 
						|
 | 
						|
private:
 | 
						|
    pthread_t   _thread;
 | 
						|
};
 | 
						|
 | 
						|
inline uint my_tid(void) { return (uint)toku_os_gettid(); }
 | 
						|
 | 
						|
inline mutex_t::mutex_t(pfs_key_t key) {
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
    _owners = 0;
 | 
						|
    _owner = _null_owner;
 | 
						|
#endif
 | 
						|
    int  r MY_ATTRIBUTE((unused)) = mysql_mutex_init(key, &_mutex, MY_MUTEX_INIT_FAST);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline mutex_t::~mutex_t() {
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
    assert_debug(_owners == 0);
 | 
						|
#endif
 | 
						|
    int  r MY_ATTRIBUTE((unused)) = mysql_mutex_destroy(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void mutex_t::reinit(pfs_key_t key) {
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
    assert_debug(_owners == 0);
 | 
						|
#endif
 | 
						|
    int  r MY_ATTRIBUTE((unused));
 | 
						|
    r = mysql_mutex_destroy(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = mysql_mutex_init(key, &_mutex, MY_MUTEX_INIT_FAST);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void mutex_t::lock(
 | 
						|
#if defined(SAFE_MUTEX) || defined(HAVE_PSI_MUTEX_INTERFACE)
 | 
						|
    const char* src_file,
 | 
						|
    uint src_line
 | 
						|
#endif  // SAFE_MUTEX || HAVE_PSI_MUTEX_INTERFACE
 | 
						|
    ) {
 | 
						|
    assert_debug(is_owned_by_me() == false);
 | 
						|
    int r MY_ATTRIBUTE((unused)) = inline_mysql_mutex_lock(&_mutex
 | 
						|
#if defined(SAFE_MUTEX) || defined(HAVE_PSI_MUTEX_INTERFACE)
 | 
						|
                                    ,
 | 
						|
                                    src_file,
 | 
						|
                                    src_line
 | 
						|
#endif  // SAFE_MUTEX || HAVE_PSI_MUTEX_INTERFACE
 | 
						|
                                    );
 | 
						|
    assert_debug(r == 0);
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
    _owners++;
 | 
						|
    _owner = pthread_self();
 | 
						|
#endif
 | 
						|
}
 | 
						|
inline void mutex_t::unlock(
 | 
						|
#if defined(SAFE_MUTEX)
 | 
						|
    const char* src_file,
 | 
						|
    uint src_line
 | 
						|
#endif  // SAFE_MUTEX
 | 
						|
    ) {
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
    assert_debug(_owners > 0);
 | 
						|
    assert_debug(is_owned_by_me());
 | 
						|
    _owners--;
 | 
						|
    _owner = _null_owner;
 | 
						|
#endif
 | 
						|
    int r MY_ATTRIBUTE((unused)) = inline_mysql_mutex_unlock(&_mutex
 | 
						|
#if defined(SAFE_MUTEX)
 | 
						|
                                      ,
 | 
						|
                                      src_file,
 | 
						|
                                      src_line
 | 
						|
#endif  // SAFE_MUTEX
 | 
						|
                                      );
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
#ifdef TOKUDB_DEBUG
 | 
						|
inline bool mutex_t::is_owned_by_me(void) const {
 | 
						|
    return pthread_equal(pthread_self(), _owner) != 0 ? true : false;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
inline rwlock_t::rwlock_t(pfs_key_t key) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = mysql_rwlock_init(key, &_rwlock);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline rwlock_t::~rwlock_t() {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = mysql_rwlock_destroy(&_rwlock);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void rwlock_t::lock_read(
 | 
						|
#ifdef HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
    const char* src_file,
 | 
						|
    uint src_line
 | 
						|
#endif  // HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
    ) {
 | 
						|
    int r;
 | 
						|
    while ((r = inline_mysql_rwlock_rdlock(&_rwlock
 | 
						|
#ifdef HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
                                           ,
 | 
						|
                                           src_file,
 | 
						|
                                           src_line
 | 
						|
#endif  // HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
                                           )) != 0) {
 | 
						|
        if (r == EBUSY || r == EAGAIN) {
 | 
						|
            time::sleep_microsec(1000);
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void rwlock_t::lock_write(
 | 
						|
#ifdef HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
    const char* src_file,
 | 
						|
    uint src_line
 | 
						|
#endif  // HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
    ) {
 | 
						|
    int r;
 | 
						|
    while ((r = inline_mysql_rwlock_wrlock(&_rwlock
 | 
						|
#ifdef HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
                                           ,
 | 
						|
                                           src_file,
 | 
						|
                                           src_line
 | 
						|
#endif  // HAVE_PSI_RWLOCK_INTERFACE
 | 
						|
                                           )) != 0) {
 | 
						|
        if (r == EBUSY || r == EAGAIN) {
 | 
						|
            time::sleep_microsec(1000);
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void rwlock_t::unlock(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = mysql_rwlock_unlock(&_rwlock);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline rwlock_t::rwlock_t(const rwlock_t&) {}
 | 
						|
inline rwlock_t& rwlock_t::operator=(const rwlock_t&) {
 | 
						|
    return *this;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
inline event_t::event_t(bool create_signalled, bool manual_reset) :
 | 
						|
    _manual_reset(manual_reset) {
 | 
						|
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_init(&_mutex, NULL);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = pthread_cond_init(&_cond, NULL);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    if (create_signalled) {
 | 
						|
        _signalled = true;
 | 
						|
    } else {
 | 
						|
        _signalled = false;
 | 
						|
    }
 | 
						|
    _pulsed = false;
 | 
						|
}
 | 
						|
inline event_t::~event_t(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_destroy(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = pthread_cond_destroy(&_cond);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void event_t::wait(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    while (_signalled == false && _pulsed == false) {
 | 
						|
        r = pthread_cond_wait(&_cond, &_mutex);
 | 
						|
        assert_debug(r == 0);
 | 
						|
    }
 | 
						|
    if (_manual_reset == false)
 | 
						|
        _signalled = false;
 | 
						|
    if (_pulsed)
 | 
						|
        _pulsed = false;
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    return;
 | 
						|
}
 | 
						|
inline void event_t::signal(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    _signalled = true;
 | 
						|
    if (_manual_reset) {
 | 
						|
        r = pthread_cond_broadcast(&_cond);
 | 
						|
        assert_debug(r == 0);
 | 
						|
    } else {
 | 
						|
        r = pthread_cond_signal(&_cond);
 | 
						|
        assert_debug(r == 0);
 | 
						|
    }
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void event_t::pulse(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    _pulsed = true;
 | 
						|
    r = pthread_cond_signal(&_cond);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline bool event_t::signalled(void) {
 | 
						|
    bool ret = false;
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    ret = _signalled;
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
inline void event_t::reset(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    _signalled = false;
 | 
						|
    _pulsed = false;
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    return;
 | 
						|
}
 | 
						|
inline event_t::event_t(const event_t&) {
 | 
						|
}
 | 
						|
inline event_t& event_t::operator=(const event_t&) {
 | 
						|
    return *this;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
inline semaphore_t::semaphore_t(
 | 
						|
    int initial_count,
 | 
						|
    int max_count) :
 | 
						|
    _interrupted(false),
 | 
						|
    _initial_count(initial_count),
 | 
						|
    _max_count(max_count) {
 | 
						|
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_init(&_mutex, NULL);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = pthread_cond_init(&_cond, NULL);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    _signalled = _initial_count;
 | 
						|
}
 | 
						|
inline semaphore_t::~semaphore_t(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_destroy(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = pthread_cond_destroy(&_cond);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline semaphore_t::E_WAIT semaphore_t::wait(void) {
 | 
						|
    E_WAIT ret;
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    while (_signalled == 0 && _interrupted == false) {
 | 
						|
        r = pthread_cond_wait(&_cond, &_mutex);
 | 
						|
        assert_debug(r == 0);
 | 
						|
    }
 | 
						|
    if (_interrupted) {
 | 
						|
        ret = E_INTERRUPTED;
 | 
						|
    } else {
 | 
						|
        _signalled--;
 | 
						|
        ret = E_SIGNALLED;
 | 
						|
    }
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
inline bool semaphore_t::signal(void) {
 | 
						|
    bool ret = false;
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    if (_signalled < _max_count) {
 | 
						|
        _signalled++;
 | 
						|
        ret = true;
 | 
						|
    }
 | 
						|
    r = pthread_cond_signal(&_cond);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
inline int semaphore_t::signalled(void) {
 | 
						|
    int ret = 0;
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    ret = _signalled;
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
inline void semaphore_t::reset(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    _signalled = 0;
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    return;
 | 
						|
}
 | 
						|
inline void semaphore_t::set_interrupt(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    _interrupted = true;
 | 
						|
    r = pthread_cond_broadcast(&_cond);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline void semaphore_t::clear_interrupt(void) {
 | 
						|
    int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
    _interrupted = false;
 | 
						|
    r = pthread_mutex_unlock(&_mutex);
 | 
						|
    assert_debug(r == 0);
 | 
						|
}
 | 
						|
inline semaphore_t::semaphore_t(const semaphore_t&) {
 | 
						|
}
 | 
						|
inline semaphore_t& semaphore_t::operator=(const semaphore_t&) {
 | 
						|
    return *this;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
inline thread_t::thread_t(void) : _thread(0) {
 | 
						|
}
 | 
						|
inline thread_t::~thread_t(void) {
 | 
						|
}
 | 
						|
inline int thread_t::start(void*(*pfn)(void*), void* arg) {
 | 
						|
    return pthread_create(&_thread, NULL, pfn, arg);
 | 
						|
}
 | 
						|
inline int thread_t::join(void** value_ptr) {
 | 
						|
    return pthread_join(_thread, value_ptr);
 | 
						|
}
 | 
						|
inline int thread_t::detach(void) {
 | 
						|
    return pthread_detach(_thread);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace thread
 | 
						|
} // namespace tokudb
 | 
						|
 | 
						|
 | 
						|
#endif // _TOKUDB_SYNC_H
 |