imgtools/imglib/boostlibrary/boost/thread/pthread/once.hpp
author Iain Williamson <iain.williamson@nokia.com>
Fri, 28 May 2010 15:15:09 +0100
changeset 579 e26b09d36de0
parent 0 044383f39525
permissions -rw-r--r--
Version 2.14.1 [Candidate 1]
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     1
#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     2
#define BOOST_THREAD_PTHREAD_ONCE_HPP
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     3
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     4
//  once.hpp
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     5
//
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     6
//  (C) Copyright 2007-8 Anthony Williams 
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     7
//
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     8
//  Distributed under the Boost Software License, Version 1.0. (See
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
     9
//  accompanying file LICENSE_1_0.txt or copy at
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    10
//  http://www.boost.org/LICENSE_1_0.txt)
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    11
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    12
#include <boost/thread/detail/config.hpp>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    13
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    14
#include <pthread.h>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    15
#include <boost/assert.hpp>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    16
#include "pthread_mutex_scoped_lock.hpp"
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    17
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    18
#include <boost/cstdint.hpp>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    19
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    20
#include <boost/config/abi_prefix.hpp>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    21
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    22
namespace boost
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    23
{
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    24
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    25
    struct once_flag
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    26
    {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    27
        boost::uintmax_t epoch;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    28
    };
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    29
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    30
    namespace detail
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    31
    {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    32
        BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    33
        BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    34
        BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    35
        BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    36
    }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    37
    
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    38
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    39
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    40
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    41
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    42
    // Based on Mike Burrows fast_pthread_once algorithm as described in
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    43
    // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    44
    template<typename Function>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    45
    void call_once(once_flag& flag,Function f)
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    46
    {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    47
        static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    48
        static boost::uintmax_t const being_initialized=uninitialized_flag+1;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    49
        boost::uintmax_t const epoch=flag.epoch;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    50
        boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    51
        
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    52
        if(epoch<this_thread_epoch)
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    53
        {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    54
            pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    55
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    56
            while(flag.epoch<=being_initialized)
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    57
            {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    58
                if(flag.epoch==uninitialized_flag)
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    59
                {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    60
                    flag.epoch=being_initialized;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    61
                    try
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    62
                    {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    63
                        pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    64
                        f();
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    65
                    }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    66
                    catch(...)
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    67
                    {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    68
                        flag.epoch=uninitialized_flag;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    69
                        BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    70
                        throw;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    71
                    }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    72
                    flag.epoch=--detail::once_global_epoch;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    73
                    BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    74
                }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    75
                else
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    76
                {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    77
                    while(flag.epoch==being_initialized)
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    78
                    {
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    79
                        BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    80
                    }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    81
                }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    82
            }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    83
            this_thread_epoch=detail::once_global_epoch;
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    84
        }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    85
    }
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    86
}
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    87
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    88
#include <boost/config/abi_suffix.hpp>
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    89
044383f39525 Convert Build package from SFL to EPL
Alex Gilkes <alex.gilkes@nokia.com>
parents:
diff changeset
    90
#endif