From: restor on
Hi,
This may not be the best place to post this question, but I didn't
know who to ask, so sorry if this is a bit off topic.

I have the following algorithm, that I want to execute in a separate
thread, so that I do not block the main one:

void findBest()
{
for ( Element elem : collection ) // foreach
{
Score score = ComputeScoreIn25minutes( elem );
if ( score > bestScore )
{
bestScore = score;
bestElem = elem;
// iterruption point here
}
}
}

I could use a future<> abstraction as described in N2094, N2185,
N2276, but I do not really have to run my algorithm to an end. I would
like to be able to obtain the best element found so far rather than
wait till the algorithm computes score for the last element in the
collection.
Thus, I would imagine starting my algorithm similarly to how a future
is created:

QFuture<elem> qfuture = run( ... );

Now, calling qfuture's default operation would interrupt the thread
rather than wait until the thread finishes.
I wonder if anyone here have ever thought of something similar. If it
is already implemented. If it has a name. Or if it is possible to
implement such an abstraction, that would not be too intrusive to
function 'findBest' from my example.

I would appreciate any help,
&rzej

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Tony Delroy on
On Apr 23, 6:22 am, restor <akrze...(a)interia.pl> wrote:
> I have the following algorithm, that I want to execute in a separate
> thread, so that I do not block the main one:
>
> void findBest()
> {
> for ( Element elem : collection ) // foreach
> {
> Score score = ComputeScoreIn25minutes( elem );
> if ( score > bestScore )
> {
> bestScore = score;
> bestElem = elem;
> // iterruption point here
> }
> }
>
> }
>
> [ snip ]
> I would
> like to be able to obtain the best element found so far rather than
> wait till the algorithm computes score for the last element in the
> collection.

Use a "mutex" (I think in Windows they're called Critical
Sections...?) to arbitrate access to bestScore and bestElem:
serialising reads from your main thread and writes from the
calculation thread. A quick 'net search should turn up the details
you need.

Tony

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Lance Diduck on
{ Please format your article to fit in 70 columns or so, definitely
less than 80 columns. Lines broken at unwanted positions make it
very hard to read or copy-and-paste. -mod }


On Apr 22, 5:22 pm, restor <akrze...(a)interia.pl> wrote:
> Hi,
> I would appreciate any help,

typedef std::pair<Score, Elem> BestScore;

BestScore Current;
boost::mutex Currentmutex;

BestScore getCurrent(){//called by any thread
boost::mutex::scoped_lock l(Currentmutex);
BestScore ret=Current;
//do not return Current directly, since many compiler will unlock
the mutex becore the copy is made
return ret;

}
void setCurrent(BestScore const& v){//only called by the thread
calculating scores
boost::mutex::scoped_lock l(Currentmutex);
Current =v;
}
void foo(){
Score score = ComputeScoreIn25minutes( elem );
if ( score > Current.first)//since there is only one thread
//doing the modifications (namely this one), unprotected
access is fine here
{
setCurrent(BestScore(score ,elem));

}
}

That is really all there is to it. If there were more than one thread
modifying Current, then it would look like
void foo2(){
Score score = ComputeScoreIn25minutes( elem );
{
boost::mutex::scoped_lock l(Currentmutex);
if ( score > Current.first)
//doing the modifications (namely this one), unprotected
access is fine here
{
Current=BestScore(score ,elem);

}
}
}

Doing this in a lock free style is far easier to componentize, but C++
has poor library support for it at the moment. But basically if it did
it would look like

linear_mutual_ptr<BestScore> Current2;
void foo3(){
Score score = ComputeScoreIn25minutes( elem );
do{
linear_ptr<BestScore> current=Current2;
if ( score > old->first)
if(Current2.compare_and_swap(current,
linear_ptr<BestScore>(new
BestScore(score ,elem)))
break;
else break;
}while(true);
//compare and swap returns true if the value in Current2 is still
the same as current, and then assigns
//Current2 to the new value (using special assembler instructions)
//else it is unchanged and returns false
//if only one thread modifies Current2 then compare_and_swap
always returns true
}
This is the same thing, except that now all threads have unblocked
access to the current best score, and can modify it at will. The
algorithm is independent of how many threads are used, can be called
recursivley, does not suffer from priority inversion, deadlock and
other bad things. mutex placement is not an issue, since it doesn't
exist. NB: lock-free does not always mean "faster" many times it is,
many times it is not.


Lance


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]