Move sigslot to proper third_party directory

Extract sigslot into separate target and move it to proper third_party
directory.

Bug: webrtc:8366
Change-Id: Id2e0712bd020bfad811947803c94553dce06d976
Reviewed-on: https://webrtc-review.googlesource.com/84141
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Niklas Enbom <niklas.enbom@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24099}
This commit is contained in:
Artem Titov 2018-07-25 15:04:28 +02:00 committed by Commit Bot
parent 960c01941d
commit e41c433502
59 changed files with 775 additions and 706 deletions

View file

@ -444,6 +444,7 @@ if (rtc_include_tests) {
"rtc_base:rtc_numerics_unittests",
"rtc_base:rtc_task_queue_unittests",
"rtc_base:sequenced_task_checker_unittests",
"rtc_base:sigslot_unittest",
"rtc_base:weak_ptr_unittests",
"rtc_base/experiments:experiments_unittests",
"system_wrappers:metrics_default",

View file

@ -2,8 +2,6 @@ This source tree contains third party source code which is governed by third
party licenses. Paths to the files and associated licenses are collected here.
Files governed by third party licenses:
rtc_base/sigslot.cc
rtc_base/sigslot.h
common_audio/fft4g.c
common_audio/signal_processing/spl_sqrt_floor.c
common_audio/signal_processing/spl_sqrt_floor_arm.S
@ -11,19 +9,6 @@ common_audio/signal_processing/spl_sqrt_floor_arm.S
Individual licenses for each file:
-------------------------------------------------------------------------------
Files:
rtc_base/sigslot.cc
rtc_base/sigslot.h
License:
// sigslot.h: Signal/Slot classes
//
// Written by Sarah Thompson (sarah@telergy.com) 2002.
//
// License: Public domain. You are free to use this code however you like, with
// the proviso that the author takes on no responsibility or liability for any
// use.
-------------------------------------------------------------------------------
Files:
common_audio/signal_processing/spl_sqrt_floor.c
common_audio/signal_processing/spl_sqrt_floor_arm.S

View file

@ -692,6 +692,7 @@ if (is_linux || is_win) {
"../api/video:video_frame_i420",
"../rtc_base:checks",
"../rtc_base:stringutils",
"../rtc_base/third_party/sigslot",
]
if (is_win) {
sources += [

View file

@ -18,7 +18,7 @@
#include "rtc_base/nethelpers.h"
#include "rtc_base/physicalsocketserver.h"
#include "rtc_base/signalthread.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
typedef std::map<int, std::string> Peers;

View file

@ -135,6 +135,7 @@ rtc_static_library("rtc_media_base") {
"../modules/audio_processing:audio_processing_statistics",
"../rtc_base:rtc_base",
"../rtc_base:rtc_base_approved",
"../rtc_base/third_party/sigslot",
"../system_wrappers:field_trial_api",
"//third_party/abseil-cpp/absl/types:optional",
]
@ -371,6 +372,7 @@ rtc_static_library("rtc_data") {
"../p2p:rtc_p2p",
"../rtc_base:rtc_base",
"../rtc_base:rtc_base_approved",
"../rtc_base/third_party/sigslot",
"../system_wrappers",
]
}
@ -455,6 +457,7 @@ if (rtc_include_tests) {
"../rtc_base:rtc_base_approved",
"../rtc_base:rtc_base_tests_utils",
"../rtc_base:rtc_task_queue_for_test",
"../rtc_base/third_party/sigslot",
"../test:test_support",
"//testing/gtest",
]

View file

@ -39,9 +39,9 @@
#include "rtc_base/dscp.h"
#include "rtc_base/logging.h"
#include "rtc_base/networkroute.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socket.h"
#include "rtc_base/stringencode.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
class Timing;

View file

@ -18,7 +18,7 @@
#include "media/base/videocapturer.h"
#include "media/base/videocommon.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
class ByteBufferReader;

View file

@ -26,7 +26,7 @@
#include "media/base/videocommon.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread_checker.h"
#include "rtc_base/timestampaligner.h"

View file

@ -22,7 +22,7 @@
#include "rtc_base/asyncinvoker.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/copyonwritebuffer.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
// For SendDataParams/ReceiveDataParams.
#include "media/base/mediachannel.h"

View file

@ -51,6 +51,7 @@ rtc_static_library("ortc") {
"../rtc_base:checks",
"../rtc_base:rtc_base",
"../rtc_base:rtc_base_approved",
"../rtc_base/third_party/sigslot",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/types:optional",
]

View file

@ -19,7 +19,7 @@
#include "ortc/rtptransportcontrolleradapter.h"
#include "pc/rtpreceiver.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace webrtc {

View file

@ -19,7 +19,7 @@
#include "ortc/rtptransportcontrolleradapter.h"
#include "pc/rtpsender.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace webrtc {

View file

@ -21,7 +21,7 @@
#include "pc/rtptransportinternaladapter.h"
#include "pc/srtptransport.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace webrtc {
// This class is a wrapper over an RtpTransport or an SrtpTransport. The base

View file

@ -26,7 +26,7 @@
#include "media/base/mediachannel.h" // For MediaConfig.
#include "pc/channelmanager.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace webrtc {

View file

@ -90,6 +90,7 @@ rtc_static_library("rtc_p2p") {
"../rtc_base:safe_minmax",
"../rtc_base:stringutils",
"../rtc_base/third_party/base64",
"../rtc_base/third_party/sigslot",
"../system_wrappers:field_trial_api",
"../system_wrappers:metrics_api",
"//third_party/abseil-cpp/absl/memory",
@ -139,6 +140,7 @@ if (rtc_include_tests) {
"../rtc_base:rtc_base",
"../rtc_base:rtc_base_approved",
"../rtc_base:rtc_base_tests_utils",
"../rtc_base/third_party/sigslot",
"../test:test_support",
"//third_party/abseil-cpp/absl/memory",
]

View file

@ -40,7 +40,7 @@
#include "rtc_base/asyncinvoker.h"
#include "rtc_base/asyncpacketsocket.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace webrtc {
class RtcEventLog;

View file

@ -20,8 +20,8 @@
#include "p2p/base/port.h"
#include "rtc_base/asyncpacketsocket.h"
#include "rtc_base/networkroute.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socket.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
struct PacketOptions;

View file

@ -36,8 +36,8 @@
#include "rtc_base/network.h"
#include "rtc_base/proxyinfo.h"
#include "rtc_base/ratetracker.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socketaddress.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace cricket {

View file

@ -20,8 +20,8 @@
#include "p2p/base/portinterface.h"
#include "rtc_base/helpers.h"
#include "rtc_base/proxyinfo.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/sslcertificate.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_checker.h"

View file

@ -14,7 +14,7 @@
#include <map>
#include <string>
#include "p2p/base/stun.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace cricket {

View file

@ -15,8 +15,8 @@
#include "p2p/base/relayserver.h"
#include "rtc_base/asynctcpsocket.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socketadapters.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace cricket {

View file

@ -23,8 +23,8 @@
#include "rtc_base/asyncinvoker.h"
#include "rtc_base/asyncpacketsocket.h"
#include "rtc_base/messagequeue.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socketaddress.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread_checker.h"
namespace rtc {

View file

@ -84,6 +84,7 @@ rtc_static_library("rtc_pc_base") {
"../rtc_base:rtc_task_queue",
"../rtc_base:stringutils",
"../rtc_base/third_party/base64",
"../rtc_base/third_party/sigslot",
"../system_wrappers:metrics_api",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/types:optional",
@ -203,6 +204,7 @@ rtc_static_library("peerconnection") {
"../rtc_base:stringutils",
"../rtc_base/experiments:congestion_controller_experiment",
"../rtc_base/third_party/base64",
"../rtc_base/third_party/sigslot",
"../stats",
"../system_wrappers",
"../system_wrappers:field_trial_api",
@ -310,6 +312,7 @@ if (rtc_include_tests) {
"../rtc_base:rtc_base_approved",
"../rtc_base:rtc_base_tests_main",
"../rtc_base:rtc_base_tests_utils",
"../rtc_base/third_party/sigslot",
"../system_wrappers:metrics_default",
"../system_wrappers:runtime_enabled_features_default",
"../test:test_support",
@ -409,6 +412,7 @@ if (rtc_include_tests) {
"../rtc_base:rtc_base_approved",
"../rtc_base:rtc_base_tests_utils",
"../rtc_base:rtc_task_queue",
"../rtc_base/third_party/sigslot",
"../test:test_support",
"../test:video_test_common",
"//third_party/abseil-cpp/absl/memory",

View file

@ -38,7 +38,7 @@
#include "rtc_base/asyncudpsocket.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/network.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace webrtc {
class AudioSinkInterface;

View file

@ -21,7 +21,7 @@
#include "pc/channel.h"
#include "rtc_base/messagehandler.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace webrtc {

View file

@ -32,8 +32,8 @@
#include "rtc_base/constructormagic.h"
#include "rtc_base/messagequeue.h"
#include "rtc_base/rtccertificate.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/sslstreamadapter.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace cricket {

View file

@ -32,8 +32,8 @@
#include "rtc_base/asyncinvoker.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/refcountedobject.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/sslstreamadapter.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
class Thread;

View file

@ -13,7 +13,7 @@
#include "api/mediastreaminterface.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace webrtc {

View file

@ -29,8 +29,8 @@
#include "rtc_base/asyncinvoker.h"
#include "rtc_base/refcount.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/sslidentity.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/timeutils.h"
namespace webrtc {

View file

@ -16,7 +16,7 @@
#include "call/rtp_demuxer.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "pc/rtptransportinternal.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

View file

@ -18,8 +18,8 @@
#include "p2p/base/icetransportinternal.h"
#include "pc/sessiondescription.h"
#include "rtc_base/networkroute.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/sslstreamadapter.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {
class CopyOnWriteBuffer;

View file

@ -14,7 +14,7 @@
#include "call/rtp_packet_sink_interface.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "pc/rtptransportinternal.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace webrtc {

View file

@ -19,7 +19,7 @@
#include "api/test/fakeconstraints.h"
#include "pc/test/fakeaudiocapturemodule.h"
#include "pc/test/fakevideotrackrenderer.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
class PeerConnectionTestWrapper
: public webrtc::PeerConnectionObserver,

View file

@ -18,7 +18,7 @@
#include "media/base/videocommon.h"
#include "pc/videotracksource.h"
#include "rtc_base/asyncinvoker.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
// VideoCapturerTrackSource implements VideoTrackSourceInterface. It owns a
// cricket::VideoCapturer and make sure the camera is started at a resolution

View file

@ -730,6 +730,7 @@ rtc_static_library("rtc_base_generic") {
"..:webrtc_common",
"../api:array_view",
"third_party/base64",
"third_party/sigslot",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/types:optional",
]
@ -817,7 +818,6 @@ rtc_static_library("rtc_base_generic") {
"rtccertificategenerator.h",
"signalthread.cc",
"signalthread.h",
"sigslot.cc",
"sigslot.h",
"sigslotrepeater.h",
"socket.cc",
@ -1034,6 +1034,7 @@ rtc_source_set("rtc_base_tests_utils") {
"../test:field_trial",
"../test:test_support",
"system:fallthrough",
"third_party/sigslot",
"//third_party/abseil-cpp/absl/memory",
]
public_deps = [
@ -1057,6 +1058,18 @@ rtc_source_set("rtc_task_queue_for_test") {
}
if (rtc_include_tests) {
rtc_source_set("sigslot_unittest") {
testonly = true
sources = [
"sigslot_unittest.cc",
]
deps = [
":rtc_base",
":rtc_base_tests_utils",
"third_party/sigslot",
]
}
rtc_source_set("rtc_base_tests_main") {
testonly = true
sources = [
@ -1275,7 +1288,6 @@ if (rtc_include_tests) {
"rtccertificate_unittest.cc",
"rtccertificategenerator_unittest.cc",
"signalthread_unittest.cc",
"sigslot_unittest.cc",
"sigslottester_unittest.cc",
"stream_unittest.cc",
"testclient_unittest.cc",
@ -1305,6 +1317,7 @@ if (rtc_include_tests) {
"../api:array_view",
"../test:fileutils",
"../test:test_support",
"third_party/sigslot",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/types:optional",
]

View file

@ -17,7 +17,7 @@
#include "rtc_base/messagehandler.h"
#include "rtc_base/refcountedobject.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h"

View file

@ -21,7 +21,7 @@
#include "rtc_base/event.h"
#include "rtc_base/refcountedobject.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace rtc {

View file

@ -13,8 +13,8 @@
#include "rtc_base/constructormagic.h"
#include "rtc_base/dscp.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socket.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/timeutils.h"
namespace rtc {

View file

@ -11,8 +11,8 @@
#ifndef RTC_BASE_ASYNCRESOLVERINTERFACE_H_
#define RTC_BASE_ASYNCRESOLVERINTERFACE_H_
#include "rtc_base/sigslot.h"
#include "rtc_base/socketaddress.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

View file

@ -11,8 +11,8 @@
#ifndef RTC_BASE_ASYNCSOCKET_H_
#define RTC_BASE_ASYNCSOCKET_H_
#include "rtc_base/sigslot.h"
#include "rtc_base/socket.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

View file

@ -25,8 +25,8 @@
#include "rtc_base/location.h"
#include "rtc_base/messagehandler.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socketserver.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread_annotations.h"
#include "rtc_base/timeutils.h"

View file

@ -22,8 +22,8 @@
#include "rtc_base/asyncresolverinterface.h"
#include "rtc_base/signalthread.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socketaddress.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

View file

@ -22,7 +22,7 @@
#include "rtc_base/ipaddress.h"
#include "rtc_base/messagehandler.h"
#include "rtc_base/networkmonitor.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#if defined(WEBRTC_POSIX)
struct ifaddrs;

View file

@ -13,7 +13,7 @@
#include "rtc_base/logging.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace rtc {

View file

@ -16,7 +16,7 @@
#include "rtc_base/checks.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/nullsocketserver.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
namespace rtc {

View file

@ -1,644 +1,14 @@
// sigslot.h: Signal/Slot classes
//
// Written by Sarah Thompson (sarah@telergy.com) 2002.
//
// License: Public domain. You are free to use this code however you like, with
// the proviso that the author takes on no responsibility or liability for any
// use.
//
// QUICK DOCUMENTATION
//
// (see also the full documentation at http://sigslot.sourceforge.net/)
//
// #define switches
// SIGSLOT_PURE_ISO:
// Define this to force ISO C++ compliance. This also disables all of
// the thread safety support on platforms where it is available.
//
// SIGSLOT_USE_POSIX_THREADS:
// Force use of Posix threads when using a C++ compiler other than gcc
// on a platform that supports Posix threads. (When using gcc, this is
// the default - use SIGSLOT_PURE_ISO to disable this if necessary)
//
// SIGSLOT_DEFAULT_MT_POLICY:
// Where thread support is enabled, this defaults to
// multi_threaded_global. Otherwise, the default is single_threaded.
// #define this yourself to override the default. In pure ISO mode,
// anything other than single_threaded will cause a compiler error.
//
// PLATFORM NOTES
//
// Win32:
// On Win32, the WEBRTC_WIN symbol must be #defined. Most mainstream
// compilers do this by default, but you may need to define it yourself
// if your build environment is less standard. This causes the Win32
// thread support to be compiled in and used automatically.
//
// Unix/Linux/BSD, etc.:
// If you're using gcc, it is assumed that you have Posix threads
// available, so they are used automatically. You can override this (as
// under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
// something other than gcc but still want to use Posix threads, you
// need to #define SIGSLOT_USE_POSIX_THREADS.
//
// ISO C++:
// If none of the supported platforms are detected, or if
// SIGSLOT_PURE_ISO is defined, all multithreading support is turned
// off, along with any code that might cause a pure ISO C++ environment
// to complain. Before you ask, gcc -ansi -pedantic won't compile this
// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
// errors that aren't really there. If you feel like investigating this,
// please contact the author.
//
//
// THREADING MODES
//
// single_threaded:
// Your program is assumed to be single threaded from the point of view
// of signal/slot usage (i.e. all objects using signals and slots are
// created and destroyed from a single thread). Behaviour if objects are
// destroyed concurrently is undefined (i.e. you'll get the occasional
// segmentation fault/memory exception).
//
// multi_threaded_global:
// Your program is assumed to be multi threaded. Objects using signals
// and slots can be safely created and destroyed from any thread, even
// when connections exist. In multi_threaded_global mode, this is
// achieved by a single global mutex (actually a critical section on
// Windows because they are faster). This option uses less OS resources,
// but results in more opportunities for contention, possibly resulting
// in more context switches than are strictly necessary.
//
// multi_threaded_local:
// Behaviour in this mode is essentially the same as
// multi_threaded_global, except that each signal, and each object that
// inherits has_slots, all have their own mutex/critical section. In
// practice, this means that mutex collisions (and hence context
// switches) only happen if they are absolutely essential. However, on
// some platforms, creating a lot of mutexes can slow down the whole OS,
// so use this option with care.
//
// USING THE LIBRARY
//
// See the full documentation at http://sigslot.sourceforge.net/
//
// Libjingle specific:
//
// This file has been modified such that has_slots and signalx do not have to be
// using the same threading requirements. E.g. it is possible to connect a
// has_slots<single_threaded> and signal0<multi_threaded_local> or
// has_slots<multi_threaded_local> and signal0<single_threaded>.
// If has_slots is single threaded the user must ensure that it is not trying
// to connect or disconnect to signalx concurrently or data race may occur.
// If signalx is single threaded the user must ensure that disconnect, connect
// or signal is not happening concurrently or data race may occur.
#ifndef RTC_BASE_SIGSLOT_H_
#define RTC_BASE_SIGSLOT_H_
#include <stdlib.h>
#include <cstring>
#include <list>
#include <set>
// On our copy of sigslot.h, we set single threading as default.
#define SIGSLOT_DEFAULT_MT_POLICY single_threaded
#if defined(SIGSLOT_PURE_ISO) || \
(!defined(WEBRTC_WIN) && !defined(__GNUG__) && \
!defined(SIGSLOT_USE_POSIX_THREADS))
#define _SIGSLOT_SINGLE_THREADED
#elif defined(WEBRTC_WIN)
#define _SIGSLOT_HAS_WIN32_THREADS
#include "rtc_base/win32.h"
#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
#define _SIGSLOT_HAS_POSIX_THREADS
#include <pthread.h>
#else
#define _SIGSLOT_SINGLE_THREADED
#endif
#ifndef SIGSLOT_DEFAULT_MT_POLICY
#ifdef _SIGSLOT_SINGLE_THREADED
#define SIGSLOT_DEFAULT_MT_POLICY single_threaded
#else
#define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
#endif
#endif
// TODO: change this namespace to rtc?
namespace sigslot {
class single_threaded {
public:
void lock() {}
void unlock() {}
};
#ifdef _SIGSLOT_HAS_WIN32_THREADS
// The multi threading policies only get compiled in if they are enabled.
class multi_threaded_global {
public:
multi_threaded_global() {
static bool isinitialised = false;
if (!isinitialised) {
InitializeCriticalSection(get_critsec());
isinitialised = true;
}
}
void lock() { EnterCriticalSection(get_critsec()); }
void unlock() { LeaveCriticalSection(get_critsec()); }
private:
CRITICAL_SECTION* get_critsec() {
static CRITICAL_SECTION g_critsec;
return &g_critsec;
}
};
class multi_threaded_local {
public:
multi_threaded_local() { InitializeCriticalSection(&m_critsec); }
multi_threaded_local(const multi_threaded_local&) {
InitializeCriticalSection(&m_critsec);
}
~multi_threaded_local() { DeleteCriticalSection(&m_critsec); }
void lock() { EnterCriticalSection(&m_critsec); }
void unlock() { LeaveCriticalSection(&m_critsec); }
private:
CRITICAL_SECTION m_critsec;
};
#endif // _SIGSLOT_HAS_WIN32_THREADS
#ifdef _SIGSLOT_HAS_POSIX_THREADS
// The multi threading policies only get compiled in if they are enabled.
class multi_threaded_global {
public:
void lock() { pthread_mutex_lock(get_mutex()); }
void unlock() { pthread_mutex_unlock(get_mutex()); }
private:
static pthread_mutex_t* get_mutex();
};
class multi_threaded_local {
public:
multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); }
multi_threaded_local(const multi_threaded_local&) {
pthread_mutex_init(&m_mutex, nullptr);
}
~multi_threaded_local() { pthread_mutex_destroy(&m_mutex); }
void lock() { pthread_mutex_lock(&m_mutex); }
void unlock() { pthread_mutex_unlock(&m_mutex); }
private:
pthread_mutex_t m_mutex;
};
#endif // _SIGSLOT_HAS_POSIX_THREADS
template <class mt_policy>
class lock_block {
public:
mt_policy* m_mutex;
lock_block(mt_policy* mtx) : m_mutex(mtx) { m_mutex->lock(); }
~lock_block() { m_mutex->unlock(); }
};
class _signal_base_interface;
class has_slots_interface {
private:
typedef void (*signal_connect_t)(has_slots_interface* self,
_signal_base_interface* sender);
typedef void (*signal_disconnect_t)(has_slots_interface* self,
_signal_base_interface* sender);
typedef void (*disconnect_all_t)(has_slots_interface* self);
const signal_connect_t m_signal_connect;
const signal_disconnect_t m_signal_disconnect;
const disconnect_all_t m_disconnect_all;
protected:
has_slots_interface(signal_connect_t conn,
signal_disconnect_t disc,
disconnect_all_t disc_all)
: m_signal_connect(conn),
m_signal_disconnect(disc),
m_disconnect_all(disc_all) {}
// Doesn't really need to be virtual, but is for backwards compatibility
// (it was virtual in a previous version of sigslot).
virtual ~has_slots_interface() {}
public:
void signal_connect(_signal_base_interface* sender) {
m_signal_connect(this, sender);
}
void signal_disconnect(_signal_base_interface* sender) {
m_signal_disconnect(this, sender);
}
void disconnect_all() { m_disconnect_all(this); }
};
class _signal_base_interface {
private:
typedef void (*slot_disconnect_t)(_signal_base_interface* self,
has_slots_interface* pslot);
typedef void (*slot_duplicate_t)(_signal_base_interface* self,
const has_slots_interface* poldslot,
has_slots_interface* pnewslot);
const slot_disconnect_t m_slot_disconnect;
const slot_duplicate_t m_slot_duplicate;
protected:
_signal_base_interface(slot_disconnect_t disc, slot_duplicate_t dupl)
: m_slot_disconnect(disc), m_slot_duplicate(dupl) {}
~_signal_base_interface() {}
public:
void slot_disconnect(has_slots_interface* pslot) {
m_slot_disconnect(this, pslot);
}
void slot_duplicate(const has_slots_interface* poldslot,
has_slots_interface* pnewslot) {
m_slot_duplicate(this, poldslot, pnewslot);
}
};
class _opaque_connection {
private:
typedef void (*emit_t)(const _opaque_connection*);
template <typename FromT, typename ToT>
union union_caster {
FromT from;
ToT to;
};
emit_t pemit;
has_slots_interface* pdest;
// Pointers to member functions may be up to 16 bytes for virtual classes,
// so make sure we have enough space to store it.
unsigned char pmethod[16];
public:
template <typename DestT, typename... Args>
_opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdest(pd) {
typedef void (DestT::*pm_t)(Args...);
static_assert(sizeof(pm_t) <= sizeof(pmethod),
"Size of slot function pointer too large.");
std::memcpy(pmethod, &pm, sizeof(pm_t));
typedef void (*em_t)(const _opaque_connection* self, Args...);
union_caster<em_t, emit_t> caster2;
caster2.from = &_opaque_connection::emitter<DestT, Args...>;
pemit = caster2.to;
}
has_slots_interface* getdest() const { return pdest; }
_opaque_connection duplicate(has_slots_interface* newtarget) const {
_opaque_connection res = *this;
res.pdest = newtarget;
return res;
}
// Just calls the stored "emitter" function pointer stored at construction
// time.
template <typename... Args>
void emit(Args... args) const {
typedef void (*em_t)(const _opaque_connection*, Args...);
union_caster<emit_t, em_t> caster;
caster.from = pemit;
(caster.to)(this, args...);
}
private:
template <typename DestT, typename... Args>
static void emitter(const _opaque_connection* self, Args... args) {
typedef void (DestT::*pm_t)(Args...);
pm_t pm;
std::memcpy(&pm, self->pmethod, sizeof(pm_t));
(static_cast<DestT*>(self->pdest)->*(pm))(args...);
}
};
template <class mt_policy>
class _signal_base : public _signal_base_interface, public mt_policy {
protected:
typedef std::list<_opaque_connection> connections_list;
_signal_base()
: _signal_base_interface(&_signal_base::do_slot_disconnect,
&_signal_base::do_slot_duplicate),
m_current_iterator(m_connected_slots.end()) {}
~_signal_base() { disconnect_all(); }
private:
_signal_base& operator=(_signal_base const& that);
public:
_signal_base(const _signal_base& o)
: _signal_base_interface(&_signal_base::do_slot_disconnect,
&_signal_base::do_slot_duplicate),
m_current_iterator(m_connected_slots.end()) {
lock_block<mt_policy> lock(this);
for (const auto& connection : o.m_connected_slots) {
connection.getdest()->signal_connect(this);
m_connected_slots.push_back(connection);
}
}
bool is_empty() {
lock_block<mt_policy> lock(this);
return m_connected_slots.empty();
}
void disconnect_all() {
lock_block<mt_policy> lock(this);
while (!m_connected_slots.empty()) {
has_slots_interface* pdest = m_connected_slots.front().getdest();
m_connected_slots.pop_front();
pdest->signal_disconnect(static_cast<_signal_base_interface*>(this));
}
// If disconnect_all is called while the signal is firing, advance the
// current slot iterator to the end to avoid an invalidated iterator from
// being dereferenced.
m_current_iterator = m_connected_slots.end();
}
#if !defined(NDEBUG)
bool connected(has_slots_interface* pclass) {
lock_block<mt_policy> lock(this);
connections_list::const_iterator it = m_connected_slots.begin();
connections_list::const_iterator itEnd = m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == pclass)
return true;
++it;
}
return false;
}
#endif
void disconnect(has_slots_interface* pclass) {
lock_block<mt_policy> lock(this);
connections_list::iterator it = m_connected_slots.begin();
connections_list::iterator itEnd = m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == pclass) {
// If we're currently using this iterator because the signal is firing,
// advance it to avoid it being invalidated.
if (m_current_iterator == it) {
m_current_iterator = m_connected_slots.erase(it);
} else {
m_connected_slots.erase(it);
}
pclass->signal_disconnect(static_cast<_signal_base_interface*>(this));
return;
}
++it;
}
}
private:
static void do_slot_disconnect(_signal_base_interface* p,
has_slots_interface* pslot) {
_signal_base* const self = static_cast<_signal_base*>(p);
lock_block<mt_policy> lock(self);
connections_list::iterator it = self->m_connected_slots.begin();
connections_list::iterator itEnd = self->m_connected_slots.end();
while (it != itEnd) {
connections_list::iterator itNext = it;
++itNext;
if (it->getdest() == pslot) {
// If we're currently using this iterator because the signal is firing,
// advance it to avoid it being invalidated.
if (self->m_current_iterator == it) {
self->m_current_iterator = self->m_connected_slots.erase(it);
} else {
self->m_connected_slots.erase(it);
}
}
it = itNext;
}
}
static void do_slot_duplicate(_signal_base_interface* p,
const has_slots_interface* oldtarget,
has_slots_interface* newtarget) {
_signal_base* const self = static_cast<_signal_base*>(p);
lock_block<mt_policy> lock(self);
connections_list::iterator it = self->m_connected_slots.begin();
connections_list::iterator itEnd = self->m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == oldtarget) {
self->m_connected_slots.push_back(it->duplicate(newtarget));
}
++it;
}
}
protected:
connections_list m_connected_slots;
// Used to handle a slot being disconnected while a signal is
// firing (iterating m_connected_slots).
connections_list::iterator m_current_iterator;
bool m_erase_current_iterator = false;
};
template <class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
class has_slots : public has_slots_interface, public mt_policy {
private:
typedef std::set<_signal_base_interface*> sender_set;
typedef sender_set::const_iterator const_iterator;
public:
has_slots()
: has_slots_interface(&has_slots::do_signal_connect,
&has_slots::do_signal_disconnect,
&has_slots::do_disconnect_all) {}
has_slots(has_slots const& o)
: has_slots_interface(&has_slots::do_signal_connect,
&has_slots::do_signal_disconnect,
&has_slots::do_disconnect_all) {
lock_block<mt_policy> lock(this);
for (auto* sender : o.m_senders) {
sender->slot_duplicate(&o, this);
m_senders.insert(sender);
}
}
~has_slots() { this->disconnect_all(); }
private:
has_slots& operator=(has_slots const&);
static void do_signal_connect(has_slots_interface* p,
_signal_base_interface* sender) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
self->m_senders.insert(sender);
}
static void do_signal_disconnect(has_slots_interface* p,
_signal_base_interface* sender) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
self->m_senders.erase(sender);
}
static void do_disconnect_all(has_slots_interface* p) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
while (!self->m_senders.empty()) {
std::set<_signal_base_interface*> senders;
senders.swap(self->m_senders);
const_iterator it = senders.begin();
const_iterator itEnd = senders.end();
while (it != itEnd) {
_signal_base_interface* s = *it;
++it;
s->slot_disconnect(p);
}
}
}
private:
sender_set m_senders;
};
template <class mt_policy, typename... Args>
class signal_with_thread_policy : public _signal_base<mt_policy> {
private:
typedef _signal_base<mt_policy> base;
protected:
typedef typename base::connections_list connections_list;
public:
signal_with_thread_policy() {}
template <class desttype>
void connect(desttype* pclass, void (desttype::*pmemfun)(Args...)) {
lock_block<mt_policy> lock(this);
this->m_connected_slots.push_back(_opaque_connection(pclass, pmemfun));
pclass->signal_connect(static_cast<_signal_base_interface*>(this));
}
void emit(Args... args) {
lock_block<mt_policy> lock(this);
this->m_current_iterator = this->m_connected_slots.begin();
while (this->m_current_iterator != this->m_connected_slots.end()) {
_opaque_connection const& conn = *this->m_current_iterator;
++(this->m_current_iterator);
conn.emit<Args...>(args...);
}
}
void operator()(Args... args) { emit(args...); }
};
// Alias with default thread policy. Needed because both default arguments
// and variadic template arguments must go at the end of the list, so we
// can't have both at once.
template <typename... Args>
using signal = signal_with_thread_policy<SIGSLOT_DEFAULT_MT_POLICY, Args...>;
// The previous verion of sigslot didn't use variadic templates, so you would
// need to write "sigslot::signal2<Arg1, Arg2>", for example.
// Now you can just write "sigslot::signal<Arg1, Arg2>", but these aliases
// exist for backwards compatibility.
template <typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal0 = signal_with_thread_policy<mt_policy>;
template <typename A1, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal1 = signal_with_thread_policy<mt_policy, A1>;
template <typename A1,
typename A2,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal2 = signal_with_thread_policy<mt_policy, A1, A2>;
template <typename A1,
typename A2,
typename A3,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal3 = signal_with_thread_policy<mt_policy, A1, A2, A3>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal4 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal5 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal6 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename A7,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal7 =
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename A7,
typename A8,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal8 =
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>;
} // namespace sigslot
#endif // RTC_BASE_SIGSLOT_H_
/*
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// This is a temporary header file to move origin header from this location
// to specified in include. Don't use this header directly, use included one
// instead.
#include "rtc_base/third_party/sigslot/sigslot.h"

View file

@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/gunit.h"
#include "rtc_base/sigslotrepeater.h"

View file

@ -21,7 +21,7 @@
// TODO(deadbeef): Actually use this, after we decide on some style points on
// using signals, so it doesn't get deleted again.
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace sigslot {

View file

@ -39,7 +39,7 @@
// /* See unit-tests for more examples */
#include "rtc_base/constructormagic.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

View file

@ -36,7 +36,7 @@
// /* See unit-tests for more examples */
#include "rtc_base/constructormagic.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

View file

@ -13,7 +13,7 @@
#include <string>
#include "rtc_base/gunit.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

View file

@ -21,7 +21,7 @@
#include "rtc_base/logging.h"
#include "rtc_base/messagehandler.h"
#include "rtc_base/messagequeue.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace rtc {

17
rtc_base/third_party/sigslot/BUILD.gn vendored Normal file
View file

@ -0,0 +1,17 @@
# Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the ../../../LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("../../../webrtc.gni")
rtc_source_set("sigslot") {
visibility = [ "*" ]
sources = [
"sigslot.cc",
"sigslot.h",
]
}

7
rtc_base/third_party/sigslot/LICENSE vendored Normal file
View file

@ -0,0 +1,7 @@
// sigslot.h: Signal/Slot classes
//
// Written by Sarah Thompson (sarah@telergy.com) 2002.
//
// License: Public domain. You are free to use this code however you like, with
// the proviso that the author takes on no responsibility or liability for any
// use.

View file

@ -0,0 +1,20 @@
Name: C++ Signal/Slot Library
Short Name: sigslot
URL: http://sigslot.sourceforge.net/
Version: 0
Date: 2018-07-09
License: Custom license
License File: LICENSE
Security Critical: yes
Description:
C++ Signal/Slot Library
This file has been modified such that has_slots and signalx do not have to be
using the same threading requirements. E.g. it is possible to connect a
has_slots<single_threaded> and signal0<multi_threaded_local> or
has_slots<multi_threaded_local> and signal0<single_threaded>.
If has_slots is single threaded the user must ensure that it is not trying
to connect or disconnect to signalx concurrently or data race may occur.
If signalx is single threaded the user must ensure that disconnect, connect
or signal is not happening concurrently or data race may occur.

View file

@ -6,7 +6,7 @@
// the proviso that the author takes on no responsibility or liability for any
// use.
#include "rtc_base/sigslot.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
namespace sigslot {

644
rtc_base/third_party/sigslot/sigslot.h vendored Normal file
View file

@ -0,0 +1,644 @@
// sigslot.h: Signal/Slot classes
//
// Written by Sarah Thompson (sarah@telergy.com) 2002.
//
// License: Public domain. You are free to use this code however you like, with
// the proviso that the author takes on no responsibility or liability for any
// use.
//
// QUICK DOCUMENTATION
//
// (see also the full documentation at http://sigslot.sourceforge.net/)
//
// #define switches
// SIGSLOT_PURE_ISO:
// Define this to force ISO C++ compliance. This also disables all of
// the thread safety support on platforms where it is available.
//
// SIGSLOT_USE_POSIX_THREADS:
// Force use of Posix threads when using a C++ compiler other than gcc
// on a platform that supports Posix threads. (When using gcc, this is
// the default - use SIGSLOT_PURE_ISO to disable this if necessary)
//
// SIGSLOT_DEFAULT_MT_POLICY:
// Where thread support is enabled, this defaults to
// multi_threaded_global. Otherwise, the default is single_threaded.
// #define this yourself to override the default. In pure ISO mode,
// anything other than single_threaded will cause a compiler error.
//
// PLATFORM NOTES
//
// Win32:
// On Win32, the WEBRTC_WIN symbol must be #defined. Most mainstream
// compilers do this by default, but you may need to define it yourself
// if your build environment is less standard. This causes the Win32
// thread support to be compiled in and used automatically.
//
// Unix/Linux/BSD, etc.:
// If you're using gcc, it is assumed that you have Posix threads
// available, so they are used automatically. You can override this (as
// under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
// something other than gcc but still want to use Posix threads, you
// need to #define SIGSLOT_USE_POSIX_THREADS.
//
// ISO C++:
// If none of the supported platforms are detected, or if
// SIGSLOT_PURE_ISO is defined, all multithreading support is turned
// off, along with any code that might cause a pure ISO C++ environment
// to complain. Before you ask, gcc -ansi -pedantic won't compile this
// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
// errors that aren't really there. If you feel like investigating this,
// please contact the author.
//
//
// THREADING MODES
//
// single_threaded:
// Your program is assumed to be single threaded from the point of view
// of signal/slot usage (i.e. all objects using signals and slots are
// created and destroyed from a single thread). Behaviour if objects are
// destroyed concurrently is undefined (i.e. you'll get the occasional
// segmentation fault/memory exception).
//
// multi_threaded_global:
// Your program is assumed to be multi threaded. Objects using signals
// and slots can be safely created and destroyed from any thread, even
// when connections exist. In multi_threaded_global mode, this is
// achieved by a single global mutex (actually a critical section on
// Windows because they are faster). This option uses less OS resources,
// but results in more opportunities for contention, possibly resulting
// in more context switches than are strictly necessary.
//
// multi_threaded_local:
// Behaviour in this mode is essentially the same as
// multi_threaded_global, except that each signal, and each object that
// inherits has_slots, all have their own mutex/critical section. In
// practice, this means that mutex collisions (and hence context
// switches) only happen if they are absolutely essential. However, on
// some platforms, creating a lot of mutexes can slow down the whole OS,
// so use this option with care.
//
// USING THE LIBRARY
//
// See the full documentation at http://sigslot.sourceforge.net/
//
// Libjingle specific:
//
// This file has been modified such that has_slots and signalx do not have to be
// using the same threading requirements. E.g. it is possible to connect a
// has_slots<single_threaded> and signal0<multi_threaded_local> or
// has_slots<multi_threaded_local> and signal0<single_threaded>.
// If has_slots is single threaded the user must ensure that it is not trying
// to connect or disconnect to signalx concurrently or data race may occur.
// If signalx is single threaded the user must ensure that disconnect, connect
// or signal is not happening concurrently or data race may occur.
#ifndef RTC_BASE_SIGSLOT_H_
#define RTC_BASE_SIGSLOT_H_
#include <stdlib.h>
#include <cstring>
#include <list>
#include <set>
// On our copy of sigslot.h, we set single threading as default.
#define SIGSLOT_DEFAULT_MT_POLICY single_threaded
#if defined(SIGSLOT_PURE_ISO) || \
(!defined(WEBRTC_WIN) && !defined(__GNUG__) && \
!defined(SIGSLOT_USE_POSIX_THREADS))
#define _SIGSLOT_SINGLE_THREADED
#elif defined(WEBRTC_WIN)
#define _SIGSLOT_HAS_WIN32_THREADS
#include "windows.h"
#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
#define _SIGSLOT_HAS_POSIX_THREADS
#include <pthread.h>
#else
#define _SIGSLOT_SINGLE_THREADED
#endif
#ifndef SIGSLOT_DEFAULT_MT_POLICY
#ifdef _SIGSLOT_SINGLE_THREADED
#define SIGSLOT_DEFAULT_MT_POLICY single_threaded
#else
#define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
#endif
#endif
// TODO: change this namespace to rtc?
namespace sigslot {
class single_threaded {
public:
void lock() {}
void unlock() {}
};
#ifdef _SIGSLOT_HAS_WIN32_THREADS
// The multi threading policies only get compiled in if they are enabled.
class multi_threaded_global {
public:
multi_threaded_global() {
static bool isinitialised = false;
if (!isinitialised) {
InitializeCriticalSection(get_critsec());
isinitialised = true;
}
}
void lock() { EnterCriticalSection(get_critsec()); }
void unlock() { LeaveCriticalSection(get_critsec()); }
private:
CRITICAL_SECTION* get_critsec() {
static CRITICAL_SECTION g_critsec;
return &g_critsec;
}
};
class multi_threaded_local {
public:
multi_threaded_local() { InitializeCriticalSection(&m_critsec); }
multi_threaded_local(const multi_threaded_local&) {
InitializeCriticalSection(&m_critsec);
}
~multi_threaded_local() { DeleteCriticalSection(&m_critsec); }
void lock() { EnterCriticalSection(&m_critsec); }
void unlock() { LeaveCriticalSection(&m_critsec); }
private:
CRITICAL_SECTION m_critsec;
};
#endif // _SIGSLOT_HAS_WIN32_THREADS
#ifdef _SIGSLOT_HAS_POSIX_THREADS
// The multi threading policies only get compiled in if they are enabled.
class multi_threaded_global {
public:
void lock() { pthread_mutex_lock(get_mutex()); }
void unlock() { pthread_mutex_unlock(get_mutex()); }
private:
static pthread_mutex_t* get_mutex();
};
class multi_threaded_local {
public:
multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); }
multi_threaded_local(const multi_threaded_local&) {
pthread_mutex_init(&m_mutex, nullptr);
}
~multi_threaded_local() { pthread_mutex_destroy(&m_mutex); }
void lock() { pthread_mutex_lock(&m_mutex); }
void unlock() { pthread_mutex_unlock(&m_mutex); }
private:
pthread_mutex_t m_mutex;
};
#endif // _SIGSLOT_HAS_POSIX_THREADS
template <class mt_policy>
class lock_block {
public:
mt_policy* m_mutex;
lock_block(mt_policy* mtx) : m_mutex(mtx) { m_mutex->lock(); }
~lock_block() { m_mutex->unlock(); }
};
class _signal_base_interface;
class has_slots_interface {
private:
typedef void (*signal_connect_t)(has_slots_interface* self,
_signal_base_interface* sender);
typedef void (*signal_disconnect_t)(has_slots_interface* self,
_signal_base_interface* sender);
typedef void (*disconnect_all_t)(has_slots_interface* self);
const signal_connect_t m_signal_connect;
const signal_disconnect_t m_signal_disconnect;
const disconnect_all_t m_disconnect_all;
protected:
has_slots_interface(signal_connect_t conn,
signal_disconnect_t disc,
disconnect_all_t disc_all)
: m_signal_connect(conn),
m_signal_disconnect(disc),
m_disconnect_all(disc_all) {}
// Doesn't really need to be virtual, but is for backwards compatibility
// (it was virtual in a previous version of sigslot).
virtual ~has_slots_interface() {}
public:
void signal_connect(_signal_base_interface* sender) {
m_signal_connect(this, sender);
}
void signal_disconnect(_signal_base_interface* sender) {
m_signal_disconnect(this, sender);
}
void disconnect_all() { m_disconnect_all(this); }
};
class _signal_base_interface {
private:
typedef void (*slot_disconnect_t)(_signal_base_interface* self,
has_slots_interface* pslot);
typedef void (*slot_duplicate_t)(_signal_base_interface* self,
const has_slots_interface* poldslot,
has_slots_interface* pnewslot);
const slot_disconnect_t m_slot_disconnect;
const slot_duplicate_t m_slot_duplicate;
protected:
_signal_base_interface(slot_disconnect_t disc, slot_duplicate_t dupl)
: m_slot_disconnect(disc), m_slot_duplicate(dupl) {}
~_signal_base_interface() {}
public:
void slot_disconnect(has_slots_interface* pslot) {
m_slot_disconnect(this, pslot);
}
void slot_duplicate(const has_slots_interface* poldslot,
has_slots_interface* pnewslot) {
m_slot_duplicate(this, poldslot, pnewslot);
}
};
class _opaque_connection {
private:
typedef void (*emit_t)(const _opaque_connection*);
template <typename FromT, typename ToT>
union union_caster {
FromT from;
ToT to;
};
emit_t pemit;
has_slots_interface* pdest;
// Pointers to member functions may be up to 16 bytes for virtual classes,
// so make sure we have enough space to store it.
unsigned char pmethod[16];
public:
template <typename DestT, typename... Args>
_opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdest(pd) {
typedef void (DestT::*pm_t)(Args...);
static_assert(sizeof(pm_t) <= sizeof(pmethod),
"Size of slot function pointer too large.");
std::memcpy(pmethod, &pm, sizeof(pm_t));
typedef void (*em_t)(const _opaque_connection* self, Args...);
union_caster<em_t, emit_t> caster2;
caster2.from = &_opaque_connection::emitter<DestT, Args...>;
pemit = caster2.to;
}
has_slots_interface* getdest() const { return pdest; }
_opaque_connection duplicate(has_slots_interface* newtarget) const {
_opaque_connection res = *this;
res.pdest = newtarget;
return res;
}
// Just calls the stored "emitter" function pointer stored at construction
// time.
template <typename... Args>
void emit(Args... args) const {
typedef void (*em_t)(const _opaque_connection*, Args...);
union_caster<emit_t, em_t> caster;
caster.from = pemit;
(caster.to)(this, args...);
}
private:
template <typename DestT, typename... Args>
static void emitter(const _opaque_connection* self, Args... args) {
typedef void (DestT::*pm_t)(Args...);
pm_t pm;
std::memcpy(&pm, self->pmethod, sizeof(pm_t));
(static_cast<DestT*>(self->pdest)->*(pm))(args...);
}
};
template <class mt_policy>
class _signal_base : public _signal_base_interface, public mt_policy {
protected:
typedef std::list<_opaque_connection> connections_list;
_signal_base()
: _signal_base_interface(&_signal_base::do_slot_disconnect,
&_signal_base::do_slot_duplicate),
m_current_iterator(m_connected_slots.end()) {}
~_signal_base() { disconnect_all(); }
private:
_signal_base& operator=(_signal_base const& that);
public:
_signal_base(const _signal_base& o)
: _signal_base_interface(&_signal_base::do_slot_disconnect,
&_signal_base::do_slot_duplicate),
m_current_iterator(m_connected_slots.end()) {
lock_block<mt_policy> lock(this);
for (const auto& connection : o.m_connected_slots) {
connection.getdest()->signal_connect(this);
m_connected_slots.push_back(connection);
}
}
bool is_empty() {
lock_block<mt_policy> lock(this);
return m_connected_slots.empty();
}
void disconnect_all() {
lock_block<mt_policy> lock(this);
while (!m_connected_slots.empty()) {
has_slots_interface* pdest = m_connected_slots.front().getdest();
m_connected_slots.pop_front();
pdest->signal_disconnect(static_cast<_signal_base_interface*>(this));
}
// If disconnect_all is called while the signal is firing, advance the
// current slot iterator to the end to avoid an invalidated iterator from
// being dereferenced.
m_current_iterator = m_connected_slots.end();
}
#if !defined(NDEBUG)
bool connected(has_slots_interface* pclass) {
lock_block<mt_policy> lock(this);
connections_list::const_iterator it = m_connected_slots.begin();
connections_list::const_iterator itEnd = m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == pclass)
return true;
++it;
}
return false;
}
#endif
void disconnect(has_slots_interface* pclass) {
lock_block<mt_policy> lock(this);
connections_list::iterator it = m_connected_slots.begin();
connections_list::iterator itEnd = m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == pclass) {
// If we're currently using this iterator because the signal is firing,
// advance it to avoid it being invalidated.
if (m_current_iterator == it) {
m_current_iterator = m_connected_slots.erase(it);
} else {
m_connected_slots.erase(it);
}
pclass->signal_disconnect(static_cast<_signal_base_interface*>(this));
return;
}
++it;
}
}
private:
static void do_slot_disconnect(_signal_base_interface* p,
has_slots_interface* pslot) {
_signal_base* const self = static_cast<_signal_base*>(p);
lock_block<mt_policy> lock(self);
connections_list::iterator it = self->m_connected_slots.begin();
connections_list::iterator itEnd = self->m_connected_slots.end();
while (it != itEnd) {
connections_list::iterator itNext = it;
++itNext;
if (it->getdest() == pslot) {
// If we're currently using this iterator because the signal is firing,
// advance it to avoid it being invalidated.
if (self->m_current_iterator == it) {
self->m_current_iterator = self->m_connected_slots.erase(it);
} else {
self->m_connected_slots.erase(it);
}
}
it = itNext;
}
}
static void do_slot_duplicate(_signal_base_interface* p,
const has_slots_interface* oldtarget,
has_slots_interface* newtarget) {
_signal_base* const self = static_cast<_signal_base*>(p);
lock_block<mt_policy> lock(self);
connections_list::iterator it = self->m_connected_slots.begin();
connections_list::iterator itEnd = self->m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == oldtarget) {
self->m_connected_slots.push_back(it->duplicate(newtarget));
}
++it;
}
}
protected:
connections_list m_connected_slots;
// Used to handle a slot being disconnected while a signal is
// firing (iterating m_connected_slots).
connections_list::iterator m_current_iterator;
bool m_erase_current_iterator = false;
};
template <class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
class has_slots : public has_slots_interface, public mt_policy {
private:
typedef std::set<_signal_base_interface*> sender_set;
typedef sender_set::const_iterator const_iterator;
public:
has_slots()
: has_slots_interface(&has_slots::do_signal_connect,
&has_slots::do_signal_disconnect,
&has_slots::do_disconnect_all) {}
has_slots(has_slots const& o)
: has_slots_interface(&has_slots::do_signal_connect,
&has_slots::do_signal_disconnect,
&has_slots::do_disconnect_all) {
lock_block<mt_policy> lock(this);
for (auto* sender : o.m_senders) {
sender->slot_duplicate(&o, this);
m_senders.insert(sender);
}
}
~has_slots() { this->disconnect_all(); }
private:
has_slots& operator=(has_slots const&);
static void do_signal_connect(has_slots_interface* p,
_signal_base_interface* sender) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
self->m_senders.insert(sender);
}
static void do_signal_disconnect(has_slots_interface* p,
_signal_base_interface* sender) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
self->m_senders.erase(sender);
}
static void do_disconnect_all(has_slots_interface* p) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
while (!self->m_senders.empty()) {
std::set<_signal_base_interface*> senders;
senders.swap(self->m_senders);
const_iterator it = senders.begin();
const_iterator itEnd = senders.end();
while (it != itEnd) {
_signal_base_interface* s = *it;
++it;
s->slot_disconnect(p);
}
}
}
private:
sender_set m_senders;
};
template <class mt_policy, typename... Args>
class signal_with_thread_policy : public _signal_base<mt_policy> {
private:
typedef _signal_base<mt_policy> base;
protected:
typedef typename base::connections_list connections_list;
public:
signal_with_thread_policy() {}
template <class desttype>
void connect(desttype* pclass, void (desttype::*pmemfun)(Args...)) {
lock_block<mt_policy> lock(this);
this->m_connected_slots.push_back(_opaque_connection(pclass, pmemfun));
pclass->signal_connect(static_cast<_signal_base_interface*>(this));
}
void emit(Args... args) {
lock_block<mt_policy> lock(this);
this->m_current_iterator = this->m_connected_slots.begin();
while (this->m_current_iterator != this->m_connected_slots.end()) {
_opaque_connection const& conn = *this->m_current_iterator;
++(this->m_current_iterator);
conn.emit<Args...>(args...);
}
}
void operator()(Args... args) { emit(args...); }
};
// Alias with default thread policy. Needed because both default arguments
// and variadic template arguments must go at the end of the list, so we
// can't have both at once.
template <typename... Args>
using signal = signal_with_thread_policy<SIGSLOT_DEFAULT_MT_POLICY, Args...>;
// The previous verion of sigslot didn't use variadic templates, so you would
// need to write "sigslot::signal2<Arg1, Arg2>", for example.
// Now you can just write "sigslot::signal<Arg1, Arg2>", but these aliases
// exist for backwards compatibility.
template <typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal0 = signal_with_thread_policy<mt_policy>;
template <typename A1, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal1 = signal_with_thread_policy<mt_policy, A1>;
template <typename A1,
typename A2,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal2 = signal_with_thread_policy<mt_policy, A1, A2>;
template <typename A1,
typename A2,
typename A3,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal3 = signal_with_thread_policy<mt_policy, A1, A2, A3>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal4 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal5 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal6 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename A7,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal7 =
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename A7,
typename A8,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal8 =
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>;
} // namespace sigslot
#endif // RTC_BASE_SIGSLOT_H_

View file

@ -16,8 +16,8 @@
#include "rtc_base/gunit.h"
#include "rtc_base/nullsocketserver.h"
#include "rtc_base/physicalsocketserver.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socketaddress.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
#if defined(WEBRTC_WIN)

View file

@ -48,6 +48,7 @@ LIB_TO_LICENSES_DICT = {
'webrtc': ['LICENSE', 'LICENSE_THIRD_PARTY'],
'zlib': ['third_party/zlib/LICENSE'],
'base64': ['rtc_base/third_party/base64/LICENSE'],
'sigslot': ['rtc_base/third_party/sigslot/LICENSE'],
'portaudio': ['modules/third_party/portaudio/LICENSE'],
'fft': ['modules/third_party/fft/LICENSE'],
'g711': ['modules/third_party/g711/LICENSE'],