diff --git a/checkin_notes b/checkin_notes index 429daf1464..1159584b30 100644 --- a/checkin_notes +++ b/checkin_notes @@ -588,3 +588,10 @@ Rom 13 Mar 2008 example_app/ uc2_graphics.C + +David 14 Mar 2008 + - added example multi-thread application + + multi_thread/ + Makefile + multi_thread.C diff --git a/multi_thread/Makefile b/multi_thread/Makefile new file mode 100644 index 0000000000..a9195c6846 --- /dev/null +++ b/multi_thread/Makefile @@ -0,0 +1,28 @@ +# This should work on Linux. Modify as needed for other platforms. + +# Do this first: +# ln -s `g++ -print-file-name=libstdc++.a` +# This creates a symbolic link to the C++ library, +# which is linked statically + +BOINC_DIR = ../../boinc +BOINC_API_DIR = $(BOINC_DIR)/api +BOINC_LIB_DIR = $(BOINC_DIR)/lib + +CXXFLAGS = -g \ + -I$(BOINC_DIR) \ + -I$(BOINC_LIB_DIR) \ + -I$(BOINC_API_DIR) \ + -L$(BOINC_API_DIR) \ + -L$(BOINC_LIB_DIR) \ + -L. + +PROGS = multi_thread + +all: $(PROGS) + +clean: + /bin/rm -f $(PROGS) + +multi_thread: multi_thread.o $(BOINC_API_DIR)/libboinc_api.a $(BOINC_LIB_DIR)/libboinc.a + $(CXX) $(CXXFLAGS) -o multi_thread multi_thread.o libstdc++.a -pthread -lboinc_api -lboinc diff --git a/multi_thread/multi_thread.C b/multi_thread/multi_thread.C new file mode 100644 index 0000000000..96ff5b9c1a --- /dev/null +++ b/multi_thread/multi_thread.C @@ -0,0 +1,149 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// This is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +// Example multi-thread BOINC application +// The main thread spawns N threads, each of which computers for X seconds +// It handles BOINC's process control messages itself. + +#include +#include +#include +#include + +#include "boinc_api.h" + +using std::vector; + +int ngflops = 10; + +#ifdef _WIN32 +typedef UINT THREAD_ID; +#else +typedef pthread_t THREAD_ID; +#endif +#define THREAD_ID_NULL 0 + +// An abstraction of threads. +// A thread function is passed a pointer to its own object, +// and sets its ID to THREAD_ID_NULL when it's finished. +// +typedef void* (*THREAD_FUNC)(void*); + +struct THREAD { + THREAD_ID id; + int index; + + void start(THREAD_FUNC); + void suspend(bool); +}; + +struct THREAD_SET { + vector threads; + void suspend(bool if_susp) { + for (unsigned int i=0; iid != THREAD_ID_NULL) t->suspend(if_susp); + } + } + bool done() { + for (unsigned int i=0; iid != THREAD_ID_NULL) return false; + } + return true; + } +}; + +#ifdef _WIN32 +THREAD_ID create_thread(void *func()) { + uintptr_t thread; + UINT thread_id; + thread = _beginthreadex( + NULL, + 16384, + func, + 0, + 0, + &thread_id + ); + if (!thread) return THREAD_ID_NULL; + return thread_id; +} +#else +void THREAD::start(THREAD_FUNC func) { + int retval; + retval = pthread_create(&id, 0, func, (void*)this); + if (retval) { + fprintf(stderr, "can't start thread\n"); + exit(1); + } +} +void THREAD::suspend(bool if_susp) { + pthread_kill(id, if_susp?SIGSTOP:SIGCONT); +} +#endif + +static void giga_flop() { + double j = 3.14159; + int i; + for (i=0; i<500000000; i++) { + j += 5.12313123; + j *= 0.5398394834; + } +} + +void* worker(void* p) { + THREAD* t = (THREAD*)p; + for (int i=0; iindex, i); + } + t->id = THREAD_ID_NULL; +} + +int main() { + int i; + THREAD_SET thread_set; + BOINC_OPTIONS options; + BOINC_STATUS status; + APP_INIT_DATA aid; + int nthreads = 4; + + options.direct_process_action = false; + boinc_init_options(&options); + boinc_get_status(&status); + boinc_get_init_data(aid); + + for (i=0; iindex = i; + t->start(worker); + thread_set.threads.push_back(t); + } + + while (1) { + if (thread_set.done()) break; + bool old_susp = status.suspended; + boinc_get_status(&status); + if (status.suspended != old_susp) { + thread_set.suspend(status.suspended); + } + } + printf("All done.\n"); +}