add front demo in this project

This commit is contained in:
lnk
2025-06-20 16:20:59 +08:00
parent b487937ad6
commit 22c6b92af2
208 changed files with 62009 additions and 7 deletions

View File

@@ -0,0 +1,35 @@
// -*- C++ -*-
// Copyright (C) 2013-2017, Vaclav Zeman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 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
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, 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.
//! @file
//! This file contains implementations of synchronization
//! primitives using the C++11 API. It does not contain any include
//! guards because it is only a fragment to be included by
//! syncprims.h.
namespace log4cplus { namespace thread { namespace impl {
#include "log4cplus/thread/impl/syncprims-pmsm.h"
} } } // namespace log4cplus { namespace thread { namespace impl {

View File

@@ -0,0 +1,90 @@
// -*- C++ -*-
// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 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
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, 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.
#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H
#define LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
#pragma once
#endif
#if ! defined (INSIDE_LOG4CPLUS)
# error "This header must not be be used outside log4cplus' implementation files."
#endif
#include <stdexcept>
#include <log4cplus/thread/syncprims.h>
#include <mutex>
#include <thread>
#include <condition_variable>
namespace log4cplus { namespace thread { namespace impl {
LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN
syncprims_throw_exception (char const * const msg,
char const * const file, int line);
class SharedMutex
: public SharedMutexImplBase
{
public:
SharedMutex ();
~SharedMutex ();
void rdlock () const;
void wrlock () const;
void rdunlock () const;
void wrunlock () const;
private:
Mutex m1;
Mutex m2;
Mutex m3;
Semaphore w;
mutable unsigned writer_count;
Semaphore r;
mutable unsigned reader_count;
SharedMutex (SharedMutex const &);
SharedMutex & operator = (SharedMutex const &);
};
} } } // namespace log4cplus { namespace thread { namespace impl {
// Include the appropriate implementations of the classes declared
// above.
#include <log4cplus/thread/impl/syncprims-cxx11.h>
#undef LOG4CPLUS_THROW_RTE
#endif // LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H

View File

@@ -0,0 +1,119 @@
// -*- C++ -*-
// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 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
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, 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.
//! @file
//! This file contains implementations of reader-writer locking
//! primitive using other primitives, IOW poor man's rwlock.
//! It does not contain any include guards because it is only a fragment
//! to be included by syncprims-{pthreads,win32}.h.
#if ! defined (INSIDE_LOG4CPLUS)
# error "This header must not be be used outside log4cplus' implementation files."
#endif
// This implements algorithm described in "Concurrent Control with "Readers"
// and "Writers"; P.J. Courtois, F. Heymans, and D.L. Parnas;
// MBLE Research Laboratory; Brussels, Belgium"
inline
SharedMutex::SharedMutex ()
: m1 ()
, m2 ()
, m3 ()
, w (1, 1)
, writer_count (0)
, r (1, 1)
, reader_count (0)
{ }
inline
SharedMutex::~SharedMutex ()
{ }
inline
void
SharedMutex::rdlock () const
{
MutexGuard m3_guard (m3);
SemaphoreGuard r_guard (r);
MutexGuard m1_guard (m1);
if (reader_count + 1 == 1)
w.lock ();
reader_count += 1;
}
inline
void
SharedMutex::rdunlock () const
{
MutexGuard m1_guard (m1);
if (reader_count - 1 == 0)
w.unlock ();
reader_count -= 1;
}
inline
void
SharedMutex::wrlock () const
{
{
MutexGuard m2_guard (m2);
if (writer_count + 1 == 1)
r.lock ();
writer_count += 1;
}
try
{
w.lock ();
}
catch (...)
{
MutexGuard m2_guard (m2);
writer_count -= 1;
throw;
}
}
inline
void
SharedMutex::wrunlock () const
{
w.unlock ();
MutexGuard m2_guard (m2);
if (writer_count - 1 == 0)
r.unlock ();
writer_count -= 1;
}

View File

@@ -0,0 +1,96 @@
// -*- C++ -*-
// Module: Log4CPLUS
// File: threads.h
// Created: 6/2001
// Author: Tad E. Smith
//
//
// Copyright 2001-2017 Tad E. Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** @file */
#ifndef LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_
#define LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
#pragma once
#endif
#if defined (_WIN32)
#include <log4cplus/config/windowsh-inc.h>
#endif
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/thread/threads.h>
#if ! defined (INSIDE_LOG4CPLUS)
# error "This header must not be be used outside log4cplus' implementation files."
#endif
namespace log4cplus { namespace thread { namespace impl {
#if defined (LOG4CPLUS_USE_PTHREADS)
typedef pthread_t os_handle_type;
typedef pthread_t os_id_type;
inline
pthread_t
getCurrentThreadId ()
{
return pthread_self ();
}
#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
typedef HANDLE os_handle_type;
typedef DWORD os_id_type;
inline
DWORD
getCurrentThreadId ()
{
return GetCurrentThreadId ();
}
#elif defined (LOG4CPLUS_SINGLE_THREADED)
typedef void * os_handle_type;
typedef int os_id_type;
inline
int
getCurrentThreadId ()
{
return 1;
}
#endif
} } } // namespace log4cplus { namespace thread { namespace impl {
#endif // LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_

View File

@@ -0,0 +1,193 @@
// -*- C++ -*-
// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 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
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, 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.
#ifndef LOG4CPLUS_THREAD_IMPL_TLS_H
#define LOG4CPLUS_THREAD_IMPL_TLS_H
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
#pragma once
#endif
#include <new>
#include <cassert>
#include <system_error>
#if ! defined (INSIDE_LOG4CPLUS)
# error "This header must not be be used outside log4cplus' implementation files."
#endif
#ifdef LOG4CPLUS_USE_PTHREADS
# include <pthread.h>
#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
# include <log4cplus/config/windowsh-inc.h>
#elif defined (LOG4CPLUS_SINGLE_THREADED)
# include <vector>
#endif
namespace log4cplus { namespace thread { namespace impl {
typedef void * tls_value_type;
#ifdef LOG4CPLUS_USE_PTHREADS
typedef pthread_key_t * tls_key_type;
typedef void (* tls_init_cleanup_func_type)(void *);
#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
typedef DWORD tls_key_type;
typedef PFLS_CALLBACK_FUNCTION tls_init_cleanup_func_type;
#elif defined (LOG4CPLUS_SINGLE_THREADED)
typedef std::size_t tls_key_type;
typedef void (* tls_init_cleanup_func_type)(void *);
#endif
inline tls_key_type tls_init (tls_init_cleanup_func_type);
inline tls_value_type tls_get_value (tls_key_type);
inline void tls_set_value (tls_key_type, tls_value_type);
inline void tls_cleanup (tls_key_type);
#if defined (LOG4CPLUS_USE_PTHREADS)
tls_key_type
tls_init (tls_init_cleanup_func_type cleanupfunc)
{
pthread_key_t * key = new pthread_key_t;
int ret = pthread_key_create (key, cleanupfunc);
if (LOG4CPLUS_UNLIKELY (ret != 0))
throw std::system_error(ret, std::system_category (),
"pthread_key_create() failed");
return key;
}
tls_value_type
tls_get_value (tls_key_type key)
{
return pthread_getspecific (*key);
}
void
tls_set_value (tls_key_type key, tls_value_type value)
{
pthread_setspecific(*key, value);
}
void
tls_cleanup (tls_key_type key)
{
pthread_key_delete (*key);
delete key;
}
#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
tls_key_type
tls_init (tls_init_cleanup_func_type cleanupfunc)
{
DWORD const slot = FlsAlloc (cleanupfunc);
if (LOG4CPLUS_UNLIKELY (slot == FLS_OUT_OF_INDEXES))
{
DWORD const eno = GetLastError ();
throw std::system_error (static_cast<int>(eno),
std::system_category (), "FlsAlloc() failed");
}
return slot;
}
tls_value_type tls_get_value (tls_key_type k)
{
return FlsGetValue (k);
}
void
tls_set_value (tls_key_type k, tls_value_type value)
{
FlsSetValue (k, value);
}
void
tls_cleanup (tls_key_type k)
{
FlsFree (k);
}
#elif defined (LOG4CPLUS_SINGLE_THREADED)
extern std::vector<tls_value_type> * tls_single_threaded_values;
tls_key_type
tls_init (tls_init_cleanup_func_type)
{
if (! tls_single_threaded_values)
tls_single_threaded_values = new std::vector<tls_value_type>;
tls_key_type key = tls_single_threaded_values->size ();
tls_single_threaded_values->resize (key + 1);
return key;
}
tls_value_type
tls_get_value (tls_key_type k)
{
assert (k < tls_single_threaded_values->size ());
return (*tls_single_threaded_values)[k];
}
void
tls_set_value (tls_key_type k, tls_value_type val)
{
assert (k < tls_single_threaded_values->size ());
(*tls_single_threaded_values)[k] = val;
}
void
tls_cleanup (tls_key_type k)
{
assert (k < tls_single_threaded_values->size ());
(*tls_single_threaded_values)[k] = 0;
}
#endif
} } } // namespace log4cplus { namespace thread { namespace impl {
#endif // LOG4CPLUS_THREAD_IMPL_TLS_H

View File

@@ -0,0 +1,359 @@
// -*- C++ -*-
// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 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
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, 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.
#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H
#define LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
#pragma once
#endif
#include <algorithm>
#if (defined (LOG4CPLUS_INLINES_ARE_EXPORTED) \
&& defined (LOG4CPLUS_BUILD_DLL)) \
|| defined (LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL)
#include <log4cplus/thread/syncprims.h>
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
# include <log4cplus/thread/impl/syncprims-impl.h>
#endif
#define LOG4CPLUS_THROW_RTE(msg) \
do { log4cplus::thread::impl::syncprims_throw_exception (msg, __FILE__, \
__LINE__); } while (0)
namespace log4cplus { namespace thread {
namespace impl
{
LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN
syncprims_throw_exception(char const * const msg,
char const * const file, int line);
}
//
//
//
LOG4CPLUS_INLINE_EXPORT
SimpleMutex::SimpleMutex ()
LOG4CPLUS_THREADED (: mtx ())
{ }
LOG4CPLUS_INLINE_EXPORT
SimpleMutex::~SimpleMutex ()
{ }
LOG4CPLUS_INLINE_EXPORT
void
SimpleMutex::lock () const
{
LOG4CPLUS_THREADED (mtx.lock ());
}
LOG4CPLUS_INLINE_EXPORT
bool
SimpleMutex::try_lock () const
{
#if defined (LOG4CPLUS_SINGLE_THREADED)
return true;
#else
return mtx.try_lock ();
#endif
}
LOG4CPLUS_INLINE_EXPORT
void
SimpleMutex::unlock () const
{
LOG4CPLUS_THREADED (mtx.unlock ());
}
//
//
//
LOG4CPLUS_INLINE_EXPORT
Mutex::Mutex ()
LOG4CPLUS_THREADED (: mtx ())
{ }
LOG4CPLUS_INLINE_EXPORT
Mutex::~Mutex ()
{ }
LOG4CPLUS_INLINE_EXPORT
void
Mutex::lock () const
{
LOG4CPLUS_THREADED (mtx.lock ());
}
LOG4CPLUS_INLINE_EXPORT
void
Mutex::unlock () const
{
LOG4CPLUS_THREADED (mtx.unlock ());
}
//
//
//
LOG4CPLUS_INLINE_EXPORT
Semaphore::Semaphore (unsigned LOG4CPLUS_THREADED (max_),
unsigned LOG4CPLUS_THREADED (initial))
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
: maximum(max_)
, val ((std::min) (maximum, initial))
#endif
{ }
LOG4CPLUS_INLINE_EXPORT
Semaphore::~Semaphore ()
{ }
LOG4CPLUS_INLINE_EXPORT
void
Semaphore::unlock () const
{
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
std::lock_guard<std::mutex> guard (mtx);
if (val >= maximum)
LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val >= max");
++val;
cv.notify_all ();
#endif
}
LOG4CPLUS_INLINE_EXPORT
void
Semaphore::lock () const
{
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
std::unique_lock<std::mutex> guard (mtx);
if (LOG4CPLUS_UNLIKELY(val > maximum))
LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val > max");
while (val == 0)
cv.wait (guard);
--val;
if (LOG4CPLUS_UNLIKELY(val >= maximum))
LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val >= max");
#endif
}
//
//
//
LOG4CPLUS_INLINE_EXPORT
ManualResetEvent::ManualResetEvent (bool LOG4CPLUS_THREADED (sig))
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
: signaled (sig)
, sigcount (0)
#endif
{ }
LOG4CPLUS_INLINE_EXPORT
ManualResetEvent::~ManualResetEvent ()
{ }
LOG4CPLUS_INLINE_EXPORT
void
ManualResetEvent::signal () const
{
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
std::unique_lock<std::mutex> guard (mtx);
signaled = true;
sigcount += 1;
cv.notify_all ();
#endif
}
LOG4CPLUS_INLINE_EXPORT
void
ManualResetEvent::wait () const
{
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
std::unique_lock<std::mutex> guard (mtx);
if (! signaled)
{
unsigned prev_count = sigcount;
do
{
cv.wait (guard);
}
while (prev_count == sigcount);
}
#endif
}
LOG4CPLUS_INLINE_EXPORT
bool
ManualResetEvent::timed_wait (unsigned long LOG4CPLUS_THREADED (msec)) const
{
#if defined (LOG4CPLUS_SINGLE_THREADED)
return true;
#else
std::unique_lock<std::mutex> guard (mtx);
if (! signaled)
{
unsigned prev_count = sigcount;
std::chrono::steady_clock::time_point const wait_until_time
= std::chrono::steady_clock::now ()
+ std::chrono::milliseconds (msec);
do
{
int ret = static_cast<int>(
cv.wait_until (guard, wait_until_time));
switch (ret)
{
case static_cast<int>(std::cv_status::no_timeout):
break;
case static_cast<int>(std::cv_status::timeout):
return false;
default:
guard.unlock ();
guard.release ();
LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait");
}
}
while (prev_count == sigcount);
}
return true;
#endif
}
LOG4CPLUS_INLINE_EXPORT
void
ManualResetEvent::reset () const
{
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
std::lock_guard<std::mutex> guard (mtx);
signaled = false;
#endif
}
//
//
//
LOG4CPLUS_INLINE_EXPORT
SharedMutexImplBase::~SharedMutexImplBase ()
{ }
//
//
//
LOG4CPLUS_INLINE_EXPORT
SharedMutex::SharedMutex ()
: sm (LOG4CPLUS_THREADED (new impl::SharedMutex))
{ }
LOG4CPLUS_INLINE_EXPORT
SharedMutex::~SharedMutex ()
{
LOG4CPLUS_THREADED (delete static_cast<impl::SharedMutex *>(sm));
}
LOG4CPLUS_INLINE_EXPORT
void
SharedMutex::rdlock () const
{
LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->rdlock ());
}
LOG4CPLUS_INLINE_EXPORT
void
SharedMutex::wrlock () const
{
LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->wrlock ());
}
LOG4CPLUS_INLINE_EXPORT
void
SharedMutex::rdunlock () const
{
LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->rdunlock ());
}
LOG4CPLUS_INLINE_EXPORT
void
SharedMutex::wrunlock () const
{
LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->wrunlock ());
}
} } // namespace log4cplus { namespace thread {
#endif // LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL
#endif // LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H

View File

@@ -0,0 +1,354 @@
// -*- C++ -*-
// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 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
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, 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.
#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_H
#define LOG4CPLUS_THREAD_SYNCPRIMS_H
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
#pragma once
#endif
#include <mutex>
#include <condition_variable>
namespace log4cplus { namespace thread {
template <typename SyncPrim>
class SyncGuard
{
public:
SyncGuard ();
SyncGuard (SyncPrim const &);
~SyncGuard ();
SyncGuard (SyncGuard const &) = delete;
SyncGuard & operator = (SyncGuard const &) = delete;
void lock ();
void unlock ();
void attach (SyncPrim const &);
void attach_and_lock (SyncPrim const &);
void detach ();
private:
SyncPrim const * sp;
};
class LOG4CPLUS_EXPORT SimpleMutex
{
public:
SimpleMutex ();
~SimpleMutex ();
SimpleMutex (SimpleMutex const &) = delete;
SimpleMutex & operator = (SimpleMutex const &) = delete;
void lock () const;
bool try_lock () const;
void unlock () const;
private:
LOG4CPLUS_THREADED (mutable std::mutex mtx;)
};
typedef SyncGuard<SimpleMutex> SimpleMutexGuard;
class LOG4CPLUS_EXPORT Mutex
{
public:
Mutex ();
~Mutex ();
Mutex (Mutex const &) = delete;
Mutex & operator = (Mutex const &) = delete;
void lock () const;
void unlock () const;
private:
LOG4CPLUS_THREADED (mutable std::recursive_mutex mtx;)
};
typedef SyncGuard<Mutex> MutexGuard;
class LOG4CPLUS_EXPORT Semaphore
{
public:
Semaphore (unsigned max, unsigned initial);
~Semaphore ();
Semaphore (Semaphore const &) = delete;
Semaphore & operator = (Semaphore const &) = delete;
void lock () const;
void unlock () const;
private:
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
mutable std::mutex mtx;
mutable std::condition_variable cv;
mutable unsigned maximum;
mutable unsigned val;
#endif
};
typedef SyncGuard<Semaphore> SemaphoreGuard;
class LOG4CPLUS_EXPORT ManualResetEvent
{
public:
explicit ManualResetEvent (bool = false);
~ManualResetEvent ();
ManualResetEvent (ManualResetEvent const &) = delete;
ManualResetEvent & operator = (ManualResetEvent const &) = delete;
void signal () const;
void wait () const;
bool timed_wait (unsigned long msec) const;
void reset () const;
private:
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
mutable std::mutex mtx;
mutable std::condition_variable cv;
mutable bool signaled;
mutable unsigned sigcount;
#endif
};
class SharedMutexImplBase
{
protected:
~SharedMutexImplBase ();
};
template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
void (SyncPrim:: * unlock_func) () const>
class SyncGuardFunc
{
public:
SyncGuardFunc (SyncPrim const &);
~SyncGuardFunc ();
void lock ();
void unlock ();
void attach (SyncPrim const &);
void detach ();
private:
SyncPrim const * sp;
SyncGuardFunc (SyncGuardFunc const &);
SyncGuardFunc & operator = (SyncGuardFunc const &);
};
class LOG4CPLUS_EXPORT SharedMutex
{
public:
SharedMutex ();
~SharedMutex ();
void rdlock () const;
void rdunlock () const;
void wrlock () const;
void wrunlock () const;
private:
SharedMutexImplBase * sm;
SharedMutex (SharedMutex const &);
SharedMutex & operator = (SharedMutex const &);
};
typedef SyncGuardFunc<SharedMutex, &SharedMutex::rdlock,
&SharedMutex::rdunlock> SharedMutexReaderGuard;
typedef SyncGuardFunc<SharedMutex, &SharedMutex::wrlock,
&SharedMutex::wrunlock> SharedMutexWriterGuard;
//
//
//
template <typename SyncPrim>
inline
SyncGuard<SyncPrim>::SyncGuard ()
: sp (0)
{ }
template <typename SyncPrim>
inline
SyncGuard<SyncPrim>::SyncGuard (SyncPrim const & m)
: sp (&m)
{
sp->lock ();
}
template <typename SyncPrim>
inline
SyncGuard<SyncPrim>::~SyncGuard ()
{
if (sp)
sp->unlock ();
}
template <typename SyncPrim>
inline
void
SyncGuard<SyncPrim>::lock ()
{
sp->lock ();
}
template <typename SyncPrim>
inline
void
SyncGuard<SyncPrim>::unlock ()
{
sp->unlock ();
}
template <typename SyncPrim>
inline
void
SyncGuard<SyncPrim>::attach (SyncPrim const & m)
{
sp = &m;
}
template <typename SyncPrim>
inline
void
SyncGuard<SyncPrim>::attach_and_lock (SyncPrim const & m)
{
attach (m);
try
{
lock();
}
catch (...)
{
detach ();
throw;
}
}
template <typename SyncPrim>
inline
void
SyncGuard<SyncPrim>::detach ()
{
sp = 0;
}
//
//
//
template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
void (SyncPrim:: * unlock_func) () const>
inline
SyncGuardFunc<SyncPrim, lock_func, unlock_func>::SyncGuardFunc (SyncPrim const & m)
: sp (&m)
{
(sp->*lock_func) ();
}
template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
void (SyncPrim:: * unlock_func) () const>
inline
SyncGuardFunc<SyncPrim, lock_func, unlock_func>::~SyncGuardFunc ()
{
if (sp)
(sp->*unlock_func) ();
}
template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
void (SyncPrim:: * unlock_func) () const>
inline
void
SyncGuardFunc<SyncPrim, lock_func, unlock_func>::lock ()
{
(sp->*lock_func) ();
}
template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
void (SyncPrim:: * unlock_func) () const>
inline
void
SyncGuardFunc<SyncPrim, lock_func, unlock_func>::unlock ()
{
(sp->*unlock_func) ();
}
template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
void (SyncPrim:: * unlock_func) () const>
inline
void
SyncGuardFunc<SyncPrim, lock_func, unlock_func>::attach (SyncPrim const & m)
{
sp = &m;
}
template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
void (SyncPrim:: * unlock_func) () const>
inline
void
SyncGuardFunc<SyncPrim, lock_func, unlock_func>::detach ()
{
sp = 0;
}
} } // namespace log4cplus { namespace thread {
#endif // LOG4CPLUS_THREAD_SYNCPRIMS_H

View File

@@ -0,0 +1,113 @@
// -*- C++ -*-
// Module: Log4CPLUS
// File: threads.h
// Created: 6/2001
// Author: Tad E. Smith
//
//
// Copyright 2001-2017 Tad E. Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** @file */
#ifndef LOG4CPLUS_THREADS_HEADER_
#define LOG4CPLUS_THREADS_HEADER_
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
#pragma once
#endif
#include <memory>
#include <thread>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/pointer.h>
namespace log4cplus { namespace thread {
LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName();
LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName2();
LOG4CPLUS_EXPORT void setCurrentThreadName(const log4cplus::tstring & name);
LOG4CPLUS_EXPORT void setCurrentThreadName2(const log4cplus::tstring & name);
LOG4CPLUS_EXPORT void yield();
LOG4CPLUS_EXPORT void blockAllSignals();
/**
* This class blocks all POSIX signals when created and unblocks them when
* destroyed.
*/
class LOG4CPLUS_EXPORT SignalsBlocker
{
public:
SignalsBlocker();
~SignalsBlocker();
private:
struct SignalsBlockerImpl;
std::unique_ptr<SignalsBlockerImpl> impl;
};
#ifndef LOG4CPLUS_SINGLE_THREADED
/**
* There are many cross-platform C++ Threading libraries. The goal of
* this class is not to replace (or match in functionality) those
* libraries. The goal of this class is to provide a simple Threading
* class with basic functionality.
*/
class LOG4CPLUS_EXPORT AbstractThread
: public virtual log4cplus::helpers::SharedObject
{
public:
AbstractThread();
// Disallow copying of instances of this class.
AbstractThread(const AbstractThread&) = delete;
AbstractThread& operator=(const AbstractThread&) = delete;
bool isRunning() const;
virtual void start();
void join () const;
virtual void run() = 0;
protected:
// Force objects to be constructed on the heap
virtual ~AbstractThread();
private:
enum Flags
{
fRUNNING = 1,
fJOINED = 2
};
std::unique_ptr<std::thread> thread;
mutable std::atomic<int> flags;
};
typedef helpers::SharedObjectPtr<AbstractThread> AbstractThreadPtr;
#endif // LOG4CPLUS_SINGLE_THREADED
} } // namespace log4cplus { namespace thread {
#endif // LOG4CPLUS_THREADS_HEADER_