added an experimental SpinLock class
This commit is contained in:
		| @ -30,6 +30,7 @@ pkginclude_HEADERS += \ | |||||||
| 	AppRoot.hpp \ | 	AppRoot.hpp \ | ||||||
| 	SocketAddress.hpp \ | 	SocketAddress.hpp \ | ||||||
| 	Socket.hpp \ | 	Socket.hpp \ | ||||||
|  | 	SpinLock.hpp \ | ||||||
| 	Thread.hpp | 	Thread.hpp | ||||||
| endif | endif | ||||||
|  |  | ||||||
|  | |||||||
| @ -91,6 +91,7 @@ host_triplet = @host@ | |||||||
| @ENABLE_CXX_TRUE@	AppRoot.hpp \ | @ENABLE_CXX_TRUE@	AppRoot.hpp \ | ||||||
| @ENABLE_CXX_TRUE@	SocketAddress.hpp \ | @ENABLE_CXX_TRUE@	SocketAddress.hpp \ | ||||||
| @ENABLE_CXX_TRUE@	Socket.hpp \ | @ENABLE_CXX_TRUE@	Socket.hpp \ | ||||||
|  | @ENABLE_CXX_TRUE@	SpinLock.hpp \ | ||||||
| @ENABLE_CXX_TRUE@	Thread.hpp | @ENABLE_CXX_TRUE@	Thread.hpp | ||||||
|  |  | ||||||
| subdir = include/qse/si | subdir = include/qse/si | ||||||
| @ -133,7 +134,8 @@ am__can_run_installinfo = \ | |||||||
| am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \ | am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \ | ||||||
| 	fio.h fs.h glob.h intr.h log.h mtx.h mux.h nwad.h nwif.h \ | 	fio.h fs.h glob.h intr.h log.h mtx.h mux.h nwad.h nwif.h \ | ||||||
| 	nwio.h pio.h rwl.h sck.h sinfo.h sio.h task.h thr.h tio.h \ | 	nwio.h pio.h rwl.h sck.h sinfo.h sio.h task.h thr.h tio.h \ | ||||||
| 	AppRoot.hpp SocketAddress.hpp Socket.hpp Thread.hpp | 	AppRoot.hpp SocketAddress.hpp Socket.hpp SpinLock.hpp \ | ||||||
|  | 	Thread.hpp | ||||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||||
| am__vpath_adj = case $$p in \ | am__vpath_adj = case $$p in \ | ||||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||||
|  | |||||||
							
								
								
									
										77
									
								
								qse/include/qse/si/SpinLock.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								qse/include/qse/si/SpinLock.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | /* | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|  |     Redistribution and use in source and binary forms, with or without | ||||||
|  |     modification, 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 BY THE AUTHOR "AS IS" AND ANY EQSERESS 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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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 _QSE_SI_SPINLOCK_CLASS_ | ||||||
|  | #define _QSE_SI_SPINLOCK_CLASS_ | ||||||
|  |  | ||||||
|  | #include <qse/Types.hpp> | ||||||
|  | #include <qse/Uncopyable.hpp> | ||||||
|  |  | ||||||
|  | QSE_BEGIN_NAMESPACE(QSE) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SpinLock | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	bool tryock() | ||||||
|  | 	{ | ||||||
|  | 		return !__sync_lock_test_and_set(&this->flag, 1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void lock () | ||||||
|  | 	{ | ||||||
|  | 		//while (!this->tryLock()); | ||||||
|  | 		while (__sync_lock_test_and_set(&this->flag, 1)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void unlock () | ||||||
|  | 	{ | ||||||
|  | 		__sync_lock_release (&this->flag); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	volatile int flag; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class ScopedSpinLock: public Uncopyable | ||||||
|  | { | ||||||
|  | 	ScopedSpinLock (SpinLock& spl): spl(spl) | ||||||
|  | 	{ | ||||||
|  | 		this->spl.lock (); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	~ScopedSpinLock () | ||||||
|  | 	{ | ||||||
|  | 		this->spl.unlock (); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	SpinLock& spl; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | QSE_END_NAMESPACE(QSE) | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @ -62,10 +62,12 @@ if ENABLE_CXX | |||||||
|  |  | ||||||
| CXXLIB = -lqsesixx -lqsecmnxx | CXXLIB = -lqsesixx -lqsecmnxx | ||||||
|  |  | ||||||
| bin_PROGRAMS += thr02 | bin_PROGRAMS += thr02 spl02 | ||||||
|  |  | ||||||
|  | spl02_SOURCES = spl02.cpp | ||||||
| thr02_SOURCES = thr02.cpp | thr02_SOURCES = thr02.cpp | ||||||
|  |  | ||||||
|  | spl02_LDADD = $(CXXLIB) $(LDADD) | ||||||
| thr02_LDADD = $(CXXLIB) $(LDADD) | thr02_LDADD = $(CXXLIB) $(LDADD) | ||||||
|  |  | ||||||
| endif | endif | ||||||
|  | |||||||
| @ -95,7 +95,7 @@ bin_PROGRAMS = aio01$(EXEEXT) dir01$(EXEEXT) fio01$(EXEEXT) \ | |||||||
| 	sio02$(EXEEXT) sio03$(EXEEXT) task01$(EXEEXT) thr01$(EXEEXT) \ | 	sio02$(EXEEXT) sio03$(EXEEXT) task01$(EXEEXT) thr01$(EXEEXT) \ | ||||||
| 	$(am__EXEEXT_1) | 	$(am__EXEEXT_1) | ||||||
| @WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS) | @WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS) | ||||||
| @ENABLE_CXX_TRUE@am__append_2 = thr02 | @ENABLE_CXX_TRUE@am__append_2 = thr02 spl02 | ||||||
| subdir = samples/si | subdir = samples/si | ||||||
| ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ||||||
| am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ | am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ | ||||||
| @ -113,7 +113,7 @@ mkinstalldirs = $(install_sh) -d | |||||||
| CONFIG_HEADER = $(top_builddir)/include/qse/config.h | CONFIG_HEADER = $(top_builddir)/include/qse/config.h | ||||||
| CONFIG_CLEAN_FILES = | CONFIG_CLEAN_FILES = | ||||||
| CONFIG_CLEAN_VPATH_FILES = | CONFIG_CLEAN_VPATH_FILES = | ||||||
| @ENABLE_CXX_TRUE@am__EXEEXT_1 = thr02$(EXEEXT) | @ENABLE_CXX_TRUE@am__EXEEXT_1 = thr02$(EXEEXT) spl02$(EXEEXT) | ||||||
| am__installdirs = "$(DESTDIR)$(bindir)" | am__installdirs = "$(DESTDIR)$(bindir)" | ||||||
| PROGRAMS = $(bin_PROGRAMS) | PROGRAMS = $(bin_PROGRAMS) | ||||||
| am_aio01_OBJECTS = aio01.$(OBJEXT) | am_aio01_OBJECTS = aio01.$(OBJEXT) | ||||||
| @ -190,6 +190,12 @@ am_sio03_OBJECTS = sio03.$(OBJEXT) | |||||||
| sio03_OBJECTS = $(am_sio03_OBJECTS) | sio03_OBJECTS = $(am_sio03_OBJECTS) | ||||||
| sio03_LDADD = $(LDADD) | sio03_LDADD = $(LDADD) | ||||||
| sio03_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) | sio03_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) | ||||||
|  | am__spl02_SOURCES_DIST = spl02.cpp | ||||||
|  | @ENABLE_CXX_TRUE@am_spl02_OBJECTS = spl02.$(OBJEXT) | ||||||
|  | spl02_OBJECTS = $(am_spl02_OBJECTS) | ||||||
|  | am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) | ||||||
|  | @ENABLE_CXX_TRUE@spl02_DEPENDENCIES = $(am__DEPENDENCIES_1) \ | ||||||
|  | @ENABLE_CXX_TRUE@	$(am__DEPENDENCIES_3) | ||||||
| am_task01_OBJECTS = task01.$(OBJEXT) | am_task01_OBJECTS = task01.$(OBJEXT) | ||||||
| task01_OBJECTS = $(am_task01_OBJECTS) | task01_OBJECTS = $(am_task01_OBJECTS) | ||||||
| task01_LDADD = $(LDADD) | task01_LDADD = $(LDADD) | ||||||
| @ -201,7 +207,6 @@ thr01_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) | |||||||
| am__thr02_SOURCES_DIST = thr02.cpp | am__thr02_SOURCES_DIST = thr02.cpp | ||||||
| @ENABLE_CXX_TRUE@am_thr02_OBJECTS = thr02.$(OBJEXT) | @ENABLE_CXX_TRUE@am_thr02_OBJECTS = thr02.$(OBJEXT) | ||||||
| thr02_OBJECTS = $(am_thr02_OBJECTS) | thr02_OBJECTS = $(am_thr02_OBJECTS) | ||||||
| am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) |  | ||||||
| @ENABLE_CXX_TRUE@thr02_DEPENDENCIES = $(am__DEPENDENCIES_1) \ | @ENABLE_CXX_TRUE@thr02_DEPENDENCIES = $(am__DEPENDENCIES_1) \ | ||||||
| @ENABLE_CXX_TRUE@	$(am__DEPENDENCIES_3) | @ENABLE_CXX_TRUE@	$(am__DEPENDENCIES_3) | ||||||
| AM_V_P = $(am__v_P_@AM_V@) | AM_V_P = $(am__v_P_@AM_V@) | ||||||
| @ -261,15 +266,15 @@ SOURCES = $(aio01_SOURCES) $(dir01_SOURCES) $(fio01_SOURCES) \ | |||||||
| 	$(fs03_SOURCES) $(glob01_SOURCES) $(log01_SOURCES) \ | 	$(fs03_SOURCES) $(glob01_SOURCES) $(log01_SOURCES) \ | ||||||
| 	$(nwad01_SOURCES) $(nwif01_SOURCES) $(nwif02_SOURCES) \ | 	$(nwad01_SOURCES) $(nwif01_SOURCES) $(nwif02_SOURCES) \ | ||||||
| 	$(pio01_SOURCES) $(rwl01_SOURCES) $(sio01_SOURCES) \ | 	$(pio01_SOURCES) $(rwl01_SOURCES) $(sio01_SOURCES) \ | ||||||
| 	$(sio02_SOURCES) $(sio03_SOURCES) $(task01_SOURCES) \ | 	$(sio02_SOURCES) $(sio03_SOURCES) $(spl02_SOURCES) \ | ||||||
| 	$(thr01_SOURCES) $(thr02_SOURCES) | 	$(task01_SOURCES) $(thr01_SOURCES) $(thr02_SOURCES) | ||||||
| DIST_SOURCES = $(aio01_SOURCES) $(dir01_SOURCES) $(fio01_SOURCES) \ | DIST_SOURCES = $(aio01_SOURCES) $(dir01_SOURCES) $(fio01_SOURCES) \ | ||||||
| 	$(fio02_SOURCES) $(fs01_SOURCES) $(fs02_SOURCES) \ | 	$(fio02_SOURCES) $(fs01_SOURCES) $(fs02_SOURCES) \ | ||||||
| 	$(fs03_SOURCES) $(glob01_SOURCES) $(log01_SOURCES) \ | 	$(fs03_SOURCES) $(glob01_SOURCES) $(log01_SOURCES) \ | ||||||
| 	$(nwad01_SOURCES) $(nwif01_SOURCES) $(nwif02_SOURCES) \ | 	$(nwad01_SOURCES) $(nwif01_SOURCES) $(nwif02_SOURCES) \ | ||||||
| 	$(pio01_SOURCES) $(rwl01_SOURCES) $(sio01_SOURCES) \ | 	$(pio01_SOURCES) $(rwl01_SOURCES) $(sio01_SOURCES) \ | ||||||
| 	$(sio02_SOURCES) $(sio03_SOURCES) $(task01_SOURCES) \ | 	$(sio02_SOURCES) $(sio03_SOURCES) $(am__spl02_SOURCES_DIST) \ | ||||||
| 	$(thr01_SOURCES) $(am__thr02_SOURCES_DIST) | 	$(task01_SOURCES) $(thr01_SOURCES) $(am__thr02_SOURCES_DIST) | ||||||
| am__can_run_installinfo = \ | am__can_run_installinfo = \ | ||||||
|   case $$AM_UPDATE_INFO_DIR in \ |   case $$AM_UPDATE_INFO_DIR in \ | ||||||
|     n|no|NO) false;; \ |     n|no|NO) false;; \ | ||||||
| @ -505,7 +510,9 @@ sio03_SOURCES = sio03.c | |||||||
| task01_SOURCES = task01.c | task01_SOURCES = task01.c | ||||||
| thr01_SOURCES = thr01.c | thr01_SOURCES = thr01.c | ||||||
| @ENABLE_CXX_TRUE@CXXLIB = -lqsesixx -lqsecmnxx | @ENABLE_CXX_TRUE@CXXLIB = -lqsesixx -lqsecmnxx | ||||||
|  | @ENABLE_CXX_TRUE@spl02_SOURCES = spl02.cpp | ||||||
| @ENABLE_CXX_TRUE@thr02_SOURCES = thr02.cpp | @ENABLE_CXX_TRUE@thr02_SOURCES = thr02.cpp | ||||||
|  | @ENABLE_CXX_TRUE@spl02_LDADD = $(CXXLIB) $(LDADD) | ||||||
| @ENABLE_CXX_TRUE@thr02_LDADD = $(CXXLIB) $(LDADD) | @ENABLE_CXX_TRUE@thr02_LDADD = $(CXXLIB) $(LDADD) | ||||||
| all: all-am | all: all-am | ||||||
|  |  | ||||||
| @ -658,6 +665,10 @@ sio03$(EXEEXT): $(sio03_OBJECTS) $(sio03_DEPENDENCIES) $(EXTRA_sio03_DEPENDENCIE | |||||||
| 	@rm -f sio03$(EXEEXT) | 	@rm -f sio03$(EXEEXT) | ||||||
| 	$(AM_V_CCLD)$(LINK) $(sio03_OBJECTS) $(sio03_LDADD) $(LIBS) | 	$(AM_V_CCLD)$(LINK) $(sio03_OBJECTS) $(sio03_LDADD) $(LIBS) | ||||||
|  |  | ||||||
|  | spl02$(EXEEXT): $(spl02_OBJECTS) $(spl02_DEPENDENCIES) $(EXTRA_spl02_DEPENDENCIES)  | ||||||
|  | 	@rm -f spl02$(EXEEXT) | ||||||
|  | 	$(AM_V_CXXLD)$(CXXLINK) $(spl02_OBJECTS) $(spl02_LDADD) $(LIBS) | ||||||
|  |  | ||||||
| task01$(EXEEXT): $(task01_OBJECTS) $(task01_DEPENDENCIES) $(EXTRA_task01_DEPENDENCIES)  | task01$(EXEEXT): $(task01_OBJECTS) $(task01_DEPENDENCIES) $(EXTRA_task01_DEPENDENCIES)  | ||||||
| 	@rm -f task01$(EXEEXT) | 	@rm -f task01$(EXEEXT) | ||||||
| 	$(AM_V_CCLD)$(LINK) $(task01_OBJECTS) $(task01_LDADD) $(LIBS) | 	$(AM_V_CCLD)$(LINK) $(task01_OBJECTS) $(task01_LDADD) $(LIBS) | ||||||
| @ -693,6 +704,7 @@ distclean-compile: | |||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio01.Po@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio01.Po@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio02.Po@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio02.Po@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio03.Po@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio03.Po@am__quote@ | ||||||
|  | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spl02.Po@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task01.Po@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task01.Po@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr01.Po@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr01.Po@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr02.Po@am__quote@ | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr02.Po@am__quote@ | ||||||
|  | |||||||
							
								
								
									
										298
									
								
								qse/samples/si/spl02.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								qse/samples/si/spl02.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,298 @@ | |||||||
|  | #include <qse/si/SpinLock.hpp> | ||||||
|  | #include <qse/si/Thread.hpp> | ||||||
|  | #include <qse/si/mtx.h> | ||||||
|  | #include <qse/si/sio.h> | ||||||
|  | #include <qse/cmn/mem.h> | ||||||
|  |  | ||||||
|  | #include <locale.h> | ||||||
|  | #if defined(_WIN32) | ||||||
|  | #	include <windows.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | static int g_stopreq = 0; | ||||||
|  |  | ||||||
|  | static QSE::SpinLock g_prmtx; | ||||||
|  |  | ||||||
|  | class MyThread: public QSE::Thread | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	MyThread(): stopreq(0) {} | ||||||
|  |  | ||||||
|  | 	int main () | ||||||
|  | 	{ | ||||||
|  | 		int i = 0; | ||||||
|  |  | ||||||
|  | 		while (!this->stopreq) | ||||||
|  | 		{ | ||||||
|  | 			g_prmtx.lock (); | ||||||
|  | 			qse_printf (QSE_T("m %p -> %d\n"), this, i); | ||||||
|  | 			g_prmtx.unlock (); | ||||||
|  | 			i++; | ||||||
|  | 			sleep (1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return i; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	int stopreq; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class Functor | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	int operator() (QSE::Thread* thr) | ||||||
|  | 	{ | ||||||
|  | 		int i = 0; | ||||||
|  | 		int* stopreqptr = (int*)thr->getContext(); | ||||||
|  |  | ||||||
|  | 		while (!*stopreqptr) | ||||||
|  | 		{ | ||||||
|  | 			g_prmtx.lock (); | ||||||
|  | 			qse_printf (QSE_T("fc %p -> %d\n"), this, i); | ||||||
|  | 			g_prmtx.unlock (); | ||||||
|  | 			i++; | ||||||
|  | 			sleep (1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return i; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static int func_ptr (QSE::Thread* thr) | ||||||
|  | { | ||||||
|  | 	int i = 0; | ||||||
|  | 	int* stopreqptr = (int*)thr->getContext(); | ||||||
|  |  | ||||||
|  | 	while (!*stopreqptr) | ||||||
|  | 	{ | ||||||
|  | 		g_prmtx.lock (); | ||||||
|  | 		qse_printf (QSE_T("fp %p -> %d\n"), thr, i); | ||||||
|  | 		g_prmtx.unlock (); | ||||||
|  | 		i++; | ||||||
|  | 		sleep (1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int test1 (void) | ||||||
|  | { | ||||||
|  | 	int localstopreq = 0; | ||||||
|  |  | ||||||
|  | #if defined(QSE_CPP_CPP11) | ||||||
|  | 	auto lambda = [](QSE::Thread* thr)->int  | ||||||
|  | 	{  | ||||||
|  | 		int i = 0; | ||||||
|  | 		int* stopreqptr = (int*)thr->getContext(); | ||||||
|  |  | ||||||
|  | 		while (!*stopreqptr) | ||||||
|  | 		{ | ||||||
|  | 			g_prmtx.lock (); | ||||||
|  | 			qse_printf (QSE_T("l %p -> %d\n"), thr, i); | ||||||
|  | 			g_prmtx.unlock (); | ||||||
|  | 			i++; | ||||||
|  | 			sleep (1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return i; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	auto lambda_with_capture = [&localstopreq](QSE::Thread* thr)->int | ||||||
|  | 	{  | ||||||
|  | 		int i = 0; | ||||||
|  |  | ||||||
|  | 		while (!localstopreq) | ||||||
|  | 		{ | ||||||
|  | 			g_prmtx.lock (); | ||||||
|  | 			qse_printf (QSE_T("lc %p -> %d\n"), thr, i); | ||||||
|  | 			g_prmtx.unlock (); | ||||||
|  | 			i++; | ||||||
|  | 			sleep (1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return i; | ||||||
|  | 	}; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	MyThread thr1; | ||||||
|  | 	thr1.setStackSize (64000); | ||||||
|  | 	if (thr1.start(QSE::Thread::SIGNALS_BLOCKED) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		qse_printf (QSE_T("cannot start thread1\n")); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	QSE::ThreadR thr2; | ||||||
|  | 	thr2.setStackSize (64000); | ||||||
|  | 	thr2.setContext (&localstopreq); | ||||||
|  | #if defined(QSE_CPP_CPP11) | ||||||
|  | 	// the lambda expression with no capture can be passed as a function pointer | ||||||
|  | 	// as long as the signature matches QSE::Thread::ThreadRoutine. | ||||||
|  | 	if (thr2.start(lambda, QSE::Thread::SIGNALS_BLOCKED) <= -1) | ||||||
|  | #else | ||||||
|  | 	if (thr2.start(func_ptr, QSE::Thread::SIGNALS_BLOCKED) <= -1) | ||||||
|  | #endif | ||||||
|  | 	{ | ||||||
|  | 		qse_printf (QSE_T("cannot start thread2\n")); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(QSE_CPP_CPP11) | ||||||
|  | 	QSE::ThreadF<decltype(lambda)> thr3 (lambda); | ||||||
|  | 	thr3.setStackSize (64000); | ||||||
|  | 	thr3.setContext (&localstopreq); | ||||||
|  | 	if (thr3.start(QSE::Thread::SIGNALS_BLOCKED) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		qse_printf (QSE_T("cannot start thread3\n")); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// turn a lambda with capture to a thread | ||||||
|  | 	QSE::ThreadF<decltype(lambda_with_capture)> thr4 (lambda_with_capture); | ||||||
|  | 	thr4.setStackSize (64000); | ||||||
|  | 	if (thr4.start(QSE::Thread::SIGNALS_BLOCKED) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		qse_printf (QSE_T("cannot start thread4\n")); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	QSE::ThreadL<int(QSE::Thread*)> thr5; | ||||||
|  | 	thr5.setStackSize (64000); | ||||||
|  | 	if (thr5.start( | ||||||
|  | 		([&localstopreq, &thr5](QSE::Thread* thr) {  | ||||||
|  | 			int i = 0; | ||||||
|  |  | ||||||
|  | 			while (!localstopreq) | ||||||
|  | 			{ | ||||||
|  | 				g_prmtx.lock (); | ||||||
|  | 				qse_printf (QSE_T("tl %p -> %d\n"), thr, i); | ||||||
|  | 				g_prmtx.unlock (); | ||||||
|  | 				i++; | ||||||
|  | 				sleep (1); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return i; | ||||||
|  | 		}),  | ||||||
|  | 		QSE::Thread::SIGNALS_BLOCKED) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		qse_printf (QSE_T("cannot start thread5\n")); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	// turn a functor to a thread | ||||||
|  | 	QSE::ThreadF<Functor> thr6; | ||||||
|  | 	thr6.setStackSize (64000); | ||||||
|  | 	thr6.setContext (&localstopreq); | ||||||
|  | 	if (thr6.start(QSE::Thread::SIGNALS_BLOCKED) <= -1) | ||||||
|  | 	{ | ||||||
|  | 		qse_printf (QSE_T("cannot start thread6\n")); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	while (!g_stopreq) | ||||||
|  | 	{ | ||||||
|  | 		if (thr1.getState() == QSE::Thread::TERMINATED &&  | ||||||
|  | 		    thr2.getState() == QSE::Thread::TERMINATED && | ||||||
|  | #if defined(QSE_CPP_CPP11) | ||||||
|  | 		    thr3.getState() == QSE::Thread::TERMINATED && | ||||||
|  | 		    thr4.getState() == QSE::Thread::TERMINATED && | ||||||
|  | 		    thr5.getState() == QSE::Thread::TERMINATED && | ||||||
|  | #endif | ||||||
|  | 		    thr6.getState() == QSE::Thread::TERMINATED) break; | ||||||
|  | 		sleep (1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (g_stopreq)  | ||||||
|  | 	{ | ||||||
|  | 		localstopreq = 1; | ||||||
|  | 		thr1.stopreq = 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	thr1.join (); | ||||||
|  | 	thr2.join (); | ||||||
|  | #if defined(QSE_CPP_CPP11) | ||||||
|  | 	thr3.join (); | ||||||
|  | 	thr4.join (); | ||||||
|  | 	thr5.join (); | ||||||
|  | #endif | ||||||
|  | 	thr6.join (); | ||||||
|  |  | ||||||
|  | 	qse_printf (QSE_T("thread1 ended with retcode %d\n"), thr1.getReturnCode()); | ||||||
|  | 	qse_printf (QSE_T("thread2 ended with retcode %d\n"), thr2.getReturnCode()); | ||||||
|  | #if defined(QSE_CPP_CPP11) | ||||||
|  | 	qse_printf (QSE_T("thread3 ended with retcode %d\n"), thr3.getReturnCode()); | ||||||
|  | 	qse_printf (QSE_T("thread4 ended with retcode %d\n"), thr4.getReturnCode()); | ||||||
|  | 	qse_printf (QSE_T("thread5 ended with retcode %d\n"), thr5.getReturnCode()); | ||||||
|  | #endif | ||||||
|  | 	qse_printf (QSE_T("thread6 ended with retcode %d\n"), thr6.getReturnCode()); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx) | ||||||
|  | { | ||||||
|  | 	g_stopreq = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void set_signal (int sig, void(*handler)(int, siginfo_t*, void*)) | ||||||
|  | { | ||||||
|  | 	struct sigaction sa; | ||||||
|  |   | ||||||
|  | 	memset (&sa, 0, sizeof(sa)); | ||||||
|  | 	/*sa.sa_handler = handler;*/ | ||||||
|  | 	sa.sa_flags = SA_SIGINFO; | ||||||
|  | 	sa.sa_sigaction = handler; | ||||||
|  | 	sigemptyset (&sa.sa_mask); | ||||||
|  |   | ||||||
|  | 	sigaction (sig, &sa, NULL); | ||||||
|  | } | ||||||
|  |   | ||||||
|  | static void set_signal_to_default (int sig) | ||||||
|  | { | ||||||
|  | 	struct sigaction sa; | ||||||
|  |   | ||||||
|  | 	memset (&sa, 0, sizeof(sa)); | ||||||
|  | 	sa.sa_handler = SIG_DFL; | ||||||
|  | 	sa.sa_flags = 0; | ||||||
|  | 	sigemptyset (&sa.sa_mask); | ||||||
|  |   | ||||||
|  | 	sigaction (sig, &sa, NULL); | ||||||
|  | } | ||||||
|  |   | ||||||
|  | int main () | ||||||
|  | { | ||||||
|  | #if defined(_WIN32) | ||||||
|  |  	char locale[100]; | ||||||
|  | 	UINT codepage = GetConsoleOutputCP(); | ||||||
|  | 	if (codepage == CP_UTF8) | ||||||
|  | 	{ | ||||||
|  | 		/*SetConsoleOUtputCP (CP_UTF8);*/ | ||||||
|  | 		qse_setdflcmgrbyid (QSE_CMGR_UTF8); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		sprintf (locale, ".%u", (unsigned int)codepage); | ||||||
|  | 		setlocale (LC_ALL, locale); | ||||||
|  | 		/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/ | ||||||
|  | 	} | ||||||
|  | #else | ||||||
|  | 	setlocale (LC_ALL, ""); | ||||||
|  | 	/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	set_signal (SIGINT, handle_sigint); | ||||||
|  |  | ||||||
|  | 	qse_open_stdsios (); | ||||||
|  | 	test1(); | ||||||
|  | 	qse_close_stdsios (); | ||||||
|  |  | ||||||
|  | 	set_signal_to_default (SIGINT); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user