Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > e7402dc2d35e679dfa225853dfccfb35 > files > 81

UpTools-devel-8.6.2-1.fc15.i686.rpm

/* UpTools v8.6
 *
 * Copyright (c) 2005-2012 Fundacion Universidad de Palermo (Argentina).
 * 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.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 4. Redistributions of any form whatsoever must retain the following
 *    acknowledgment: 'This product includes software developed by the
 *    "Universidad de Palermo, Argentina" (http://www.palermo.edu/).'
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS 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 COPYRIGHT
 * HOLDER OR CONTRIBUTORS 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.
 */
#include <UpTools/UpThreadWorkDistributor.h>
#include <UpTools/UpArch.h>

#include <iostream>
#include <unistd.h>

using namespace std;

#define MINSIZE_DOUBLE  600000

#define DEFAULTDATASIZE 8000000

#define DEFAULTTHREADCOUNT 8

// #define USE_WAITCOMPLETION 1



#ifndef USE_WAITCOMPLETION
	UpSemaphore sem(0);
#endif



// This class sums the numbers in the semi-open interval [begin,end).
// Example: if begin=1 and end=4  then the result will be 1+2+3=6.
// This class is going to be split and distributed between various threads
// by the UpThreadWorkDistributor in order to accelerate its work.
// (Of course it is much faster to use the well known formula to
// calculate this, but this program is a simple example to test the
// acceleration of the work by splitting it and ditributing it
// between several threads).
class SplittableSum : public UpWorkSplittable {
	private:
		unsigned long long begin, end;
		unsigned long long *saveResult;
		unsigned long long result;
		unsigned long long size;
		UpTimeVal* uptv;

	public:
		SplittableSum(unsigned long long _begin,unsigned long long _end,
						  unsigned long long *_saveResult=0, UpTimeVal* _uptv=0)
						 : begin(_begin), end(_end), saveResult(_saveResult),
							size(end-begin), uptv(_uptv)
						 { }

		~SplittableSum() {
			if( uptv!=0 ) *uptv = duration;
			if( saveResult ) {
				// UpThreadWorkDistributor will delete this work, so we save
				// the result if it is the base work
				*saveResult=result;
				#ifndef USE_WAITCOMPLETION
					// we need to unblock main thread using the semaphore here
					if(saveResult) sem.post();
				#endif
			}
		}

		SplittableSum* split() {
//			if( size<MINSIZE_DOUBLE ) return 0;
			size >>=1; // 
			unsigned long long middle( begin+size );
			// we do not set saveResult on splitted instances of this work
			SplittableSum* ret( new SplittableSum( middle, end, 0, 0 ) );
			end = middle;
			return ret;
		}

		void action() {
			register unsigned long long res( 0 );
			for( register unsigned long long x( begin ) ; x<end ; ++x )
				res += x;
			result = res;
		}

		void join( UpWorkSplittable* s ) {
			result += ((SplittableSum*)s)->result;
		}

		char joinType() {
			//return 't';
			return 's';
		}

		bool exceedHwThreads() {
			return true;
		}

		void show(ostream& o) const { o<<'('<<begin<<'-'<<(end-1)<<')'; }
};



int main(int argc, char *argv[]) {
	unsigned long long dataSize( DEFAULTDATASIZE );
	unsigned int threadCount( DEFAULTTHREADCOUNT );
	if( argc>1 ) threadCount << string(argv[1]);
	if( argc>2 ) dataSize << string(argv[2]);
	if( threadCount>32 ) threadCount=32;
	cout<<"Usage: "<<argv[0]<<" [threadCount] [endOfSum]"<<endl;
	cout<<"Summing up numbers from 1 to "<<dataSize<<" using "
		<<threadCount<<" threads"<<endl;
	UpThreadWorkDistributor ld(threadCount);
	ld.setWorkMemoryLength(10);

	unsigned long long result( 0 );
	UpTimeVal duration;

	// UpThreadWorkDistributor will delete this work after completing it
	SplittableSum* sp ( new SplittableSum( 1, dataSize+1, &result, &duration ) );

	cout<<"processing data...";

#if USE_WAITCOMPLETION
// *** case 1 ***************************************************************
// We call ld.processWork(...) with waitCompletion.
// The work will be distributed between the threads owned by the
// UpThreadWorkDistributor *and* the calling thread, so ld.processWork(..)
// will return after completing the work
	ld.processWork( sp, true );
// *** end of case 1 *********************************************************

#else
// *** case 2 **************************************************************
// We call processWork without waitCompletion.
// The work will be distributed between the threads owned by the
// UpThreadWorkDistributor only. ld.processWork(...) will return immediately
// without waiting the work to complete.
	ld.processWork( sp );
// So we block this thread on a semaphore waiting for the finished work
// to unblock us
	sem.wait();
/* ** end of case 2 ********************************************************/
#endif

	std::string txt;
	txt << "result: " << result << "\ndata processing duration: " << duration
		 << " checkValue = " << ( (result==(dataSize*(dataSize+1)/2)) ? "OK" : "ERR" );
	cout<<txt<<endl;


	return 0;
}