/*******************************************************************************
* Copyright 2013 Analog Devices, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/
package com.analog.lyric.dimple.solvers.core.multithreading.phasealgorithm;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.eclipse.jdt.annotation.Nullable;
import com.analog.lyric.dimple.schedulers.scheduleEntry.IScheduleEntry;
import com.analog.lyric.dimple.solvers.interfaces.ISolverFactorGraph;
/*
* Responsible for picking of a chunk of schedule entries,
* updating the entries, and then stealing work until there's nothing left.
*
* Package protected
*/
class WorkerWithStealing implements Callable<Object>
{
private final ISolverFactorGraph _solverGraph;
private final ConcurrentLinkedQueue<IScheduleEntry> [] _deques;
private final int _which;
private final ArrayList<IScheduleEntry> _nodes;
private final boolean _stealing;
WorkerWithStealing(
ISolverFactorGraph solverGraph,
ArrayList<IScheduleEntry> nodes,
int which, ConcurrentLinkedQueue<IScheduleEntry> [] deques,
boolean stealing)
{
_solverGraph = solverGraph;
_which = which;
_deques = deques;
_nodes= nodes;
_stealing = stealing;
}
@Override
public @Nullable Object call() throws Exception
{
//Which thread am I?
int which = _which;
//Figure out how many nodes I shold pick off.
int nodesPerThread = _nodes.size() / _deques.length;
int first = _which*nodesPerThread;
int last = first + nodesPerThread - 1;
//If I'm the last thread, I'm responsible for the last guy.
if (which == _deques.length - 1)
last = _nodes.size()-1;
//Add the schedule entries to my queue.
for (int i = first; i <= last; i++)
{
IScheduleEntry tmp = _nodes.get(i);
_deques[which].add(tmp);
}
//Pick off the first guy
IScheduleEntry n = _deques[which].poll();
//Until there's nothing left.
while (n != null)
{
//update the schedule entry.
_solverGraph.runScheduleEntry(n);
//get the next guy.
n = _deques[which].poll();
if (n == null && _stealing)
{
//If I'm out of work, see if I can steal work from any of the other guys.
for (int i = 0; i < _deques.length; i++)
{
//Start after my entry so not everyone looks from the beginning.
n = _deques[(_which + i) % _deques.length].poll();
//If I still find no work, we're done.
if (n != null)
break;
}
}
}
return null;
}
}