├── .idea
└── vcs.xml
├── CMakeLists.txt
├── SigSlotTest
├── SigSlotTest.sln
└── SigSlotTest
│ ├── SigSlotTest.vcxproj.filters
│ └── SigSlotTest.vcxproj
├── conanfile.py
├── README.md
├── .gitattributes
├── .gitignore
├── .github
└── workflows
│ └── gtest.yml
├── test
├── sigslot.cc
└── main.cpp
├── example.cc
├── sigslot
└── sigslot.h
└── conan_provider.cmake
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.13)
2 | project(sigslot)
3 |
4 | # GoogleTest requires at least C++14, coroutines need C++20
5 | set(CMAKE_CXX_STANDARD 20)
6 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
7 |
8 | find_package(GTest)
9 | find_package(sentry)
10 | enable_testing()
11 | add_executable(sigslot-test
12 | test/sigslot.cc
13 | test/main.cpp
14 | )
15 | target_link_libraries(sigslot-test PUBLIC gtest::gtest sentry-native::sentry-native)
16 | target_include_directories(sigslot-test SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
17 | target_compile_definitions(sigslot-test PRIVATE DWD_GTEST_SENTRY=1)
18 | include(GoogleTest)
19 | gtest_discover_tests(sigslot-test)
20 |
21 | if (UNIX)
22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines")
23 | endif ()
24 | if (WIN32)
25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /await")
26 | endif()
27 |
28 | install(DIRECTORY sigslot TYPE INCLUDE)
--------------------------------------------------------------------------------
/SigSlotTest/SigSlotTest.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2013 for Windows Desktop
4 | VisualStudioVersion = 12.0.30723.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SigSlotTest", "SigSlotTest\SigSlotTest.vcxproj", "{62CD295D-A6DE-480C-9AE8-2AF3BCE333A5}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Release|Win32 = Release|Win32
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {62CD295D-A6DE-480C-9AE8-2AF3BCE333A5}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {62CD295D-A6DE-480C-9AE8-2AF3BCE333A5}.Debug|Win32.Build.0 = Debug|Win32
16 | {62CD295D-A6DE-480C-9AE8-2AF3BCE333A5}.Release|Win32.ActiveCfg = Release|Win32
17 | {62CD295D-A6DE-480C-9AE8-2AF3BCE333A5}.Release|Win32.Build.0 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/SigSlotTest/SigSlotTest/SigSlotTest.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 | Header Files
25 |
26 |
27 |
--------------------------------------------------------------------------------
/conanfile.py:
--------------------------------------------------------------------------------
1 | from conan import ConanFile
2 | from conan.tools.cmake import CMakeDeps, CMakeToolchain, CMake, cmake_layout
3 | from conan.tools.files import copy
4 |
5 | class Siglot(ConanFile):
6 | name = "st-sigslot"
7 | license = "MIT"
8 | author = "Dave Cridland "
9 | url = "https://github.com/dwd/SigSlot"
10 | description = "A simple header-only Signal/Slot C++ library"
11 | topics = ("signal", "slot")
12 | exports_sources = "sigslot/*", "CMakeLists.txt", "test/*"
13 | no_copy_source = True
14 | options = {
15 | "tests": [True, False]
16 | }
17 | default_options = {
18 | "tests": False
19 | }
20 | settings = "os", "compiler", "build_type", "arch"
21 |
22 | def configure(self):
23 | if not self.options.get_safe("tests"):
24 | self.settings.clear()
25 | else:
26 | self.options["sentry-native"].backend = "inproc"
27 |
28 | def requirements(self):
29 | if self.options.get_safe("tests"):
30 | self.requires("gtest/1.12.1")
31 | self.requires("sentry-native/0.7.15")
32 |
33 | def layout(self):
34 | if self.options.tests:
35 | cmake_layout(self)
36 | else:
37 | self.folders.source = '.'
38 |
39 | def generate(self):
40 | if self.options.get_safe("tests"):
41 | deps = CMakeDeps(self)
42 | deps.generate()
43 | cmake = CMakeToolchain(self)
44 | cmake.generate()
45 |
46 | def build(self):
47 | if self.options.get_safe("tests"):
48 | cmake = CMake(self)
49 | cmake.configure()
50 | cmake.build()
51 |
52 | def package(self):
53 | copy(self, "*.h", self.source_folder, self.package_folder + '/include')
54 |
55 | def package_info(self):
56 | self.cpp_info.includedirs = ["include"]
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # sigslot - C++11 Signal/Slot library
2 |
3 | Originally written by Sarah Thompson.
4 |
5 | Various patches and fixes applied by Cat Nap Games:
6 |
7 | To make this compile under Xcode 4.3 with Clang 3.0 I made some changes myself and also used some diffs published in the original project's Sourceforge forum.
8 | I don't remember which ones though.
9 |
10 | C++11-erization (and C++2x-erixation) by Dave Cridland:
11 |
12 | See example.cc for some documentation and a walk-through example, or read the tests.
13 |
14 | This is public domain; no copyright is claimed or asserted.
15 |
16 | No warranty is implied or offered either.
17 |
18 | ## Tagging and version
19 |
20 | Until recently, I'd say just use HEAD. But some people are really keen on tags, so I'll do some semantic version tagging on this.
21 |
22 | ## Promising, yet oddly vague and sometimes outright misleading documentation
23 |
24 | This library is a pure header library, and consists of four header files:
25 |
26 |
27 |
28 | This contains a sigslot::signal class, and a sigslot::has_slots class.
29 |
30 | Signals can be connected to arbitrary functions, but in order to handle disconnect on lifetime termination, there's a "has_slots" base class to make it simpler.
31 |
32 | Loosely, calling "emit(...)" on the signal will then call all the connected "slots", which are just arbitrary functions.
33 |
34 | If a class is derived (publicly) from has_slots, you can pass in the instance of the class you want to control the lifetime. For calling a specific member directly, that's an easy decision; but if you pass in a lambda or some other arbitrary function, it might not be.
35 |
36 | If there's nothing obvious to hand, something still needs to control the scope - leaving out the has_slots argument therefore returns you a (deliberately undocumented) placeholder class, which acts in lieu of a has_slots derived class of your choice.
37 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
19 | !packages/*/build/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 | *.cachefile
56 |
57 | # Visual Studio profiler
58 | *.psess
59 | *.vsp
60 | *.vspx
61 |
62 | # Guidance Automation Toolkit
63 | *.gpState
64 |
65 | # ReSharper is a .NET coding add-in
66 | _ReSharper*/
67 | *.[Rr]e[Ss]harper
68 |
69 | # TeamCity is a build add-in
70 | _TeamCity*
71 |
72 | # DotCover is a Code Coverage Tool
73 | *.dotCover
74 |
75 | # NCrunch
76 | *.ncrunch*
77 | .*crunch*.local.xml
78 |
79 | # Installshield output folder
80 | [Ee]xpress/
81 |
82 | # DocProject is a documentation generator add-in
83 | DocProject/buildhelp/
84 | DocProject/Help/*.HxT
85 | DocProject/Help/*.HxC
86 | DocProject/Help/*.hhc
87 | DocProject/Help/*.hhk
88 | DocProject/Help/*.hhp
89 | DocProject/Help/Html2
90 | DocProject/Help/html
91 |
92 | # Click-Once directory
93 | publish/
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
100 | #packages/
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 |
136 | #LightSwitch generated files
137 | GeneratedArtifacts/
138 | _Pvt_Extensions/
139 | ModelManifest.xml
140 |
141 | # =========================
142 | # Windows detritus
143 | # =========================
144 |
145 | # Windows image file caches
146 | Thumbs.db
147 | ehthumbs.db
148 |
149 | # Folder config file
150 | Desktop.ini
151 |
152 | # Recycle Bin used on file shares
153 | $RECYCLE.BIN/
154 |
155 | # Mac desktop service store files
156 | .DS_Store
157 |
--------------------------------------------------------------------------------
/.github/workflows/gtest.yml:
--------------------------------------------------------------------------------
1 | name: gtest
2 |
3 | on:
4 | - push
5 | - pull_request
6 |
7 | jobs:
8 | gtest:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v4
13 | with:
14 | fetch-depth: 0
15 | - name: Figure out version
16 | id: tag
17 | run: |
18 | TAG=$(git describe --tags --abbrev=0)
19 | COMMITS_SINCE_TAG=$(git rev-list ${TAG}..HEAD --count)
20 | if [ "${COMMITS_SINCE_TAG}" -eq 0 ]; then
21 | echo "VERSION=${TAG}" >> $GITHUB_ENV
22 | else
23 | echo "VERSION="$(git describe --tags --abbrev=8) >> $GITHUB_ENV
24 | fi
25 | - name: Cache Conan2 dependencies
26 | uses: actions/cache@v3
27 | with:
28 | path: ~/.conan2
29 | key: ${{ runner.os }}-conan2-${{ hashFiles('**/conanfile.py') }}
30 | restore-keys: |
31 | ${{ runner.os }}-conan2-
32 | - name: Set up Python 3.8 for gcovr
33 | uses: actions/setup-python@v4
34 | - name: SonarQube install
35 | uses: SonarSource/sonarcloud-github-c-cpp@v3
36 | - name: Install Conan
37 | run: pip install conan
38 | - name: Configure Conan Profile
39 | run: |
40 | conan profile detect -e
41 | conan remote add conan-nexus https://nexus.cridland.io/repository/dwd-conan --force
42 | conan remote login conan-nexus ci --password ${{ secrets.NEXUS_PASSWORD }}
43 | - name: Conan Deps (Debug)
44 | run: conan install . -s build_type=Debug -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
45 | - name: Conan Deps (Debug)
46 | run: conan install . -s build_type=Debug -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
47 | - name: Conan Deps (Release)
48 | run: conan install . -s build_type=Release -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
49 | - name: Conan Deps (RelWithDebInfo)
50 | run: conan install . -s build_type=RelWithDebInfo -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
51 | - name: Conan Deps (Debug+Tests)
52 | run: conan install . -o tests=True -s build_type=Debug -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
53 | - name: CMake tests
54 | run: cmake -B gh-build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="conan_provider.cmake" -DCONAN_INSTALL_ARGS="-o=tests=True;--settings=compiler.cppstd=gnu23;--build=missing;--version=${{ env.VERSION }}"
55 | - name: Build
56 | run: cmake --build gh-build
57 | - name: Run Tests
58 | run: cd gh-build && ./sigslot-test
59 | - name: Create package (Debug)
60 | run: conan create . -s build_type=Debug -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
61 | - name: Create package (Release)
62 | run: conan create . -s build_type=Release -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
63 | - name: Create package (RelWithDebInfo)
64 | run: conan create . -s build_type=RelWithDebInfo -s compiler.cppstd=gnu23 -b missing --version=${{ env.VERSION }}
65 | - name: Upload
66 | run: conan upload -r conan-nexus --confirm 'st-sigslot/*'
67 |
--------------------------------------------------------------------------------
/test/sigslot.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Created by dave on 28/03/2024.
3 | //
4 |
5 | #include
6 | #include
7 |
8 | template
9 | class Sink : public sigslot::has_slots {
10 | public:
11 | std::optional> result;
12 | void slot(Args... args) {
13 | result.emplace(args...);
14 | }
15 | void reset() {
16 | result.reset();
17 | }
18 | };
19 |
20 | template<>
21 | class Sink : public sigslot::has_slots {
22 | public:
23 | bool result = false;
24 | void slot() {
25 | result = true;
26 | }
27 | void reset() {
28 | result = false;
29 | }
30 | };
31 |
32 | TEST(Simple, test_bool) {
33 | Sink sink;
34 | EXPECT_FALSE(sink.result.has_value());
35 | sigslot::signal signal;
36 | signal.connect(&sink, &Sink::slot);
37 | signal(true);
38 | EXPECT_TRUE(sink.result.has_value());
39 | EXPECT_TRUE(std::get<0>(*sink.result));
40 | sink.reset();
41 | signal(false);
42 | EXPECT_TRUE(sink.result.has_value());
43 | EXPECT_FALSE(std::get<0>(*sink.result));
44 | }
45 |
46 |
47 | TEST(Simple, test_bool_disconnect) {
48 | sigslot::signal signal;
49 | signal(true);
50 | {
51 | Sink sink;
52 | EXPECT_FALSE(sink.result.has_value());
53 | sigslot::signal signal;
54 | signal.connect(&sink, &Sink::slot);
55 | signal(true);
56 | EXPECT_TRUE(sink.result.has_value());
57 | EXPECT_TRUE(std::get<0>(*sink.result));
58 | }
59 | signal(false);
60 | }
61 |
62 |
63 | TEST(Simple, test_bool_oneshot) {
64 | Sink sink;
65 | EXPECT_FALSE(sink.result.has_value());
66 | sigslot::signal signal;
67 | signal.connect(&sink, &Sink::slot, true);
68 | signal(true);
69 | EXPECT_TRUE(sink.result.has_value());
70 | EXPECT_TRUE(std::get<0>(*sink.result));
71 | sink.reset();
72 | signal(false);
73 | EXPECT_FALSE(sink.result.has_value());
74 | }
75 |
76 |
77 | TEST(Simple, test_void) {
78 | Sink sink;
79 | EXPECT_FALSE(sink.result);
80 | sigslot::signal<> signal;
81 | signal.connect(&sink, &Sink::slot);
82 | signal();
83 | EXPECT_TRUE(sink.result);
84 | sink.reset();
85 | signal();
86 | EXPECT_TRUE(sink.result);
87 | }
88 |
89 |
90 | TEST(Simple, test_void_oneshot) {
91 | Sink sink;
92 | EXPECT_FALSE(sink.result);
93 | sigslot::signal<> signal;
94 | signal.connect(&sink, &Sink::slot, true);
95 | signal();
96 | EXPECT_TRUE(sink.result);
97 | sink.reset();
98 | signal();
99 | EXPECT_FALSE(sink.result);
100 | }
101 |
102 | TEST(Simple, test_raii_slot) {
103 | Sink sink;
104 | EXPECT_FALSE(sink.result);
105 | sigslot::signal<> signal;
106 | {
107 | auto scope_slot = signal.connect([&sink]() {
108 | sink.slot();
109 | });
110 | signal();
111 | EXPECT_TRUE(sink.result);
112 | sink.reset();
113 | EXPECT_FALSE(sink.result);
114 | signal();
115 | EXPECT_TRUE(sink.result);
116 | }
117 | sink.reset();
118 | signal();
119 | EXPECT_FALSE(sink.result);
120 | }
121 |
--------------------------------------------------------------------------------
/SigSlotTest/SigSlotTest/SigSlotTest.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {62CD295D-A6DE-480C-9AE8-2AF3BCE333A5}
15 | Win32Proj
16 | SigSlotTest
17 |
18 |
19 |
20 | Application
21 | true
22 | v120
23 | Unicode
24 |
25 |
26 | Application
27 | false
28 | v120
29 | true
30 | Unicode
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | true
44 |
45 |
46 | false
47 |
48 |
49 |
50 |
51 |
52 | Level3
53 | Disabled
54 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
55 | true
56 | ../../
57 |
58 |
59 | Console
60 | true
61 |
62 |
63 |
64 |
65 | Level3
66 |
67 |
68 | MaxSpeed
69 | true
70 | true
71 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
72 | true
73 |
74 |
75 | Console
76 | true
77 | true
78 | true
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/example.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include