I've written a simple lock-free single-consumer/-producer queue.
It's supposed to work like this:
at any time many consumers may read from it
at any time multiple producers can write to it, added elements will
be made available later
after write modification is finished, we call "makePushedElementsAvailable()", so that consumers can read the newly added elements
.
template<typename T, int Size>
class MCMPQueue
{
public:
MCMPQueue();
bool tryPushLater(const T &element);
bool tryPop(T &element);
void makePushedElementsAvailable();
protected:
private:
T elements[Size];
std::atomic<int> iHead, iTail, iWrite;
};
template<typename T, int Size>
MCMPQueue<T, Size>::SCMPQueue() : iHead(0), iTail(0), iWrite(0)
{
}
template<typename T, int Size>
void MCMPQueue<T, Size>::makePushedElementsAvailable()
{
iTail.store(iWrite.load());
}
template<typename T, int Size>
bool MCMPQueue<T, Size>::tryPop(T &element)
{
int newIndex;
int index;
do {
index = iHead.load();
if (index == iTail.load())
return false;
newIndex = index + 1;
} while (!iHead.compare_exchange_weak(index, newIndex));
index = index % Size;
element = elements[index];
return true;
}
template<typename T, int Size>
bool MCMPQueue<T, Size>::tryPushLater(const T &element)
{
int newIndex;
int index;
do {
index = iWrite.load();
if (index - iHead.load() >= Size)
return false;
newIndex = index + 1;
} while (!iWrite.compare_exchange_weak(index, newIndex));
index = index % Size;
elements[index] = element;
return true;
}
So far this seems to work fine, I'd like to have it checked by some others though please. Is there a simpler way than making the elements available after all updating has finished?
Thanks.
Related
#include<iostream>
using namespace std;
void quickSort(int input[], int start, int end)
{
// your code goes here
}
void quickSort(int input[], int size)
{
quickSort(input, 0, size - 1);
}
*/
void swap(int* a,int* b){
int temp=*a;
*a=*b;
*b=temp;
}
int count(int input[],int start,int end ){
static int c=0;
if(start==end)
return c;
if(input[start]>input[end])
c++;
return count(input,start,end-1);
}
int partionArray(int input[],int start,int end ){
int c=count(input,start,end);
int pi=c+start;
swap(&input[start],&input[pi]);
int i=start;
int j=end;
while(i<pi&&j>pi)
{
if(input[i]<input[pi])
{
i++;
}
else if(input[j]>=input[pi])
{
j--;
}
else
{
swap(&input[i],&input[j]);
i++;
j--;
}
}
return pi;
}
void qs(int input[],int start, int end){
if(start>=end)
return;
int pi=partionArray(input,start,end);
qs(input,start,pi-1);
qs(input,pi+1,end);
}
void quickSort(int input[], int size) {
qs(input,0,size-1);
}
int main(){
int n;
cin >> n;
int *input = new int[n];
for(int i = 0; i < n; i++) {
cin >> input[i];
}
quickSort(input, n);
for(int i = 0; i < n; i++) {
cout << input[i] << " ";
}
delete [] input;
}
Sort an array A using Quick Sort. Using reccursion is the question.
Input format :
Line 1 : Integer n i.e. Array size
Line 2 : Array elements (separated by space)
Output format :
Array elements in increasing order (separated by space)
Constraints :
1 <= n <= 10^3
What did i do wrong in this code pls can any one explain?Is every thing right with this code?
I have been trying to play around with backtracking. From my understanding these two codes are doing same thing but somehow I got different outcomes.
I am just trying to use some type of template to start with.
cout<<i<<endl;
backtrack(i+1);
backtrack(i+1);
and
for(int i=start; i<n; i++){
cout<<i<<endl;
backtrack(i+1);
}
The first one gets 5 as outcome and the second one gets six when I have the input of
nums=[1,1,1,1,1]
target = 3
public class Solution {
int count = 0;
public int findTargetSumWays(int[] nums, int S) {
calculate(nums, 0, 0, S);
return count;
}
public void calculate(int[] nums, int i, int sum, int S) {
if (i == nums.length) {
if (sum == S) {
count++;
}
} else {
calculate(nums, i + 1, sum + nums[i], S);
calculate(nums, i + 1, sum - nums[i], S);
}
}
}
class Solution {
public:
int count;
void backtrack(vector<int>& nums, int target, int start, int sum){
if(start==nums.size()){
if(sum==target){
count++;
}
return;
}
else{
for(int i=start; i<nums.size(); i++){
//sum+=nums[i];
backtrack(nums, target, i+1, sum+nums[i]);
sum-=nums[i];
}
}
}
int findTargetSumWays(vector<int>& nums, int target) {
count=0;
int sum=0;
int total=0;
for(auto x:nums)total+=x;
vector<vector<int>> dp;
backtrack(nums, target, 0, sum);
return count;
}
};
I am trying to implement a Dijkstra's algorithm into a fork/join threadpool (consists the main threadpool with a global task queue and N threads with its own task queue) based on Dijkstra's Solution of a problem in concurrent programming control and Frigo's and Leiserson's and Randall's The implementation of the cilk-5 multithreaded language.
But, it seems too complicated. So, I used Filter Lock from Art of Multiprocessor Programming as following:
Book's implementation
class Filter implements Lock {
int[] level;
int[] victim;
public Filter(int n) {
level = new int[n];
victim = new int[n]; // use 1..n-1
for (int i = 0; i < n; i++) {
level[i] = 0;
}
}
public void lock() {
int me = ThreadID.get();
for (int i = 1; i < n; i++) { //attempt level 1
level[me] = i;
victim[i] = me;
// spin while conflicts exist
while ((∃k != me) (level[k] >= i && victim[i] == me)) {};
}
}
public void unlock() {
int me = ThreadID.get();
level[me] = 0;
}
}
My implementation in threadpool
static int* flag;
static int* victim;
const int MAX = 1e9;
int ans = 0;
int nthreads = 10;
struct pt
{
int id;
pthread_t thread;
};
static bool existK(int j, int i, int nthreads){
for (int k = 0; k < nthreads ; k++){
if (flag[k] >= j && k != i)
{
return true;
}
}
return false;
}
void lock_init(void)
{
flag = (int *) calloc(nthreads, sizeof(int));
victim = (int *) calloc(nthreads, sizeof(int));
}
// Executed before entering critical section
void lock(int i)
{
for (int j = 1; j < nthreads; j++){
flag[i] = j;
victim[j] = i;
while (existK(j, i, nthreads) && victim[j] == i);
}
}
// Executed after leaving critical section
void unlock(int i)
{
flag[i] = 0;
}
// in main()
void* func(void *pw)
{
while (true) {
lock(threadID);
// working on its own queue if there is a task and
// after it finishes this task, call unlock(threadID) and call continue;
//if the global queue has tasks left, work on it and call unlock and continue
//if the other worker queue has tasks left, work on it and call unlock and continue
}
}
// Driver code
int main()
{
struct pt** ptr;
lock_init();
ptr = ((struct pt **)malloc(sizeof(struct pt *) * nthreads));
for (int i = 0; i < nthreads; i++){
ptr[i] = malloc(sizeof(struct pt));
(ptr[i])->id = i;
pthread_create(&(ptr[i])->thread, NULL, func, ptr[i]);
}
for (int i = 0; i < nthreads; i++){
pthread_join((ptr[i])->thread, NULL);
}
return 0;
}
However, with my implementation, the main loop is much slower than just using the pthread_mutex_lock and pthread_mutex_unlock. I am not sure if I use the algorithm in a wrong place or my algorithm is wrong at this point.
Additionally, I am wondering how to stealing tasks to work on from the
other workers’ queues in an efficient way (locating the worker with available tasks)
I am building an app with a treeview and I created a model which derives from QAbstractItemModel. I can manipulate the tree by dropping a file (dragging the file from outside of the app into the app) and drag-and-drop items within the tree.
The problem is that the file drop into the app doesn't always work since I re-implemented the function mimeData(const QModelIndexList &indexes). Sometimes and only when there is a selected item in the tree (which provides a valid item index to the function mimeData), the file drop doesn't work because the function mimeData is called but the function dropMimeData is never called.
I had to re-implement the function mimeData to be able to create my own mimeData which is used during drag-and-drop within the tree. This mimeData is used in the function dropMimeData, which works fine.
It looks like that the function mimeData should not be called during the file drop as the application knows already the mimeData format: text/uri-list.
My function dropMimeData processes both my own mimeData format and text/uri-list format.
Does anybody have the same issue or have any thoughts on this?
Again it is not like if it was not working at all, it only fails some of the time.
Any help or thoughts would be great.
Cheers.
The following might be totally unrelated, it is something I came across while trying to debug this. It looks like that there might be relation with the state of the window: QEvent::WindowActivate or QEvent::WindowDeactivate. During the file drop, the window becomes inactive and active again but the problem seems to occur when the window fails to become active again. ?
I added the source code to reproduce the problem. Drop a file into the app. Select the item in the tree. Drop more files. Sometime the drop doesn't work???
// main.cpp
#include "dragdropmainwindow.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
DragDropMainWindow w;
w.show();
return a.exec();
}
// dragdropmainwindow.h
#ifndef DRAGDROPMAINWINDOW_H
#define DRAGDROPMAINWINDOW_H
#include <QtGui/QMainWindow>
#include "ui_dragdropmainwindow.h"
#include "ControlTreeView.h"
class DragDropMainWindow : public QMainWindow
{
Q_OBJECT
public:
DragDropMainWindow(QWidget *parent = 0, Qt::WFlags flags = 0);
~DragDropMainWindow();
private:
Ui::DragDropMainWindowClass m_ui;
ControlTreeView *m_controlTree;
};
#endif // DRAGDROPMAINWINDOW_H
// dragdropmainwindow.cpp
#include "dragdropmainwindow.h"
DragDropMainWindow::DragDropMainWindow(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
m_ui.setupUi(this);
// Create a model to control the view
m_controlTree = new ControlTreeView(NULL);
m_ui.m_treeView->setModel(m_controlTree);
}
DragDropMainWindow::~DragDropMainWindow()
{
}
// ControlTreeView.h
#pragma once
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QStringList>
#include <QVector>
#include <QList>
class TreeItem
{
public:
TreeItem(const QVector<QVariant> &data, TreeItem *parent = 0);
~TreeItem();
TreeItem *child(int number);
int childCount() const;
int columnCount() const;
QVariant data(int column) const;
bool insertChildren(int position, int count, int columns);
bool insertColumns(int position, int columns);
TreeItem *parent();
bool removeChildren(int position, int count);
bool removeColumns(int position, int columns);
int childNumber() const;
bool setData(int column, const QVariant &value);
private:
QList<TreeItem*> childItems;
QVector<QVariant> itemData;
TreeItem *parentItem;
};
class ControlTreeView : public QAbstractItemModel
{
Q_OBJECT
public:
enum TREE_COLUMNS
{
eCOLUMN_FILENAME
};
ControlTreeView(QObject *parent);
~ControlTreeView(void);
QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex()) const;
QModelIndex parent (const QModelIndex & index) const;
int rowCount (const QModelIndex & parent = QModelIndex()) const;
int columnCount (const QModelIndex & parent = QModelIndex()) const;
QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags (const QModelIndex & index) const;
bool setData (const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
bool insertRows (int row, int count, const QModelIndex & parent = QModelIndex());
//bool insertColumns (int column, int count, const QModelIndex & parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex & parent = QModelIndex());
//bool removeColumns (int column, int count, const QModelIndex & parent = QModelIndex());
bool dropMimeData (const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent);
Qt::DropActions supportedDropActions() const;
QStringList mimeTypes () const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
bool setHeaderData(int section, Qt::Orientation orientation,
const QVariant &value, int role);
private:
TreeItem *getItem(const QModelIndex &jobIndex) const;
TreeItem *m_rootItem; // Root of the view tree
};
// ControlTreeView.cpp
#include "ControlTreeView.h"
#include <QtGui>
#include <QtGui/QGraphicsView>
class TreeColumn
{
public:
ControlTreeView::TREE_COLUMNS m_enumColumn;
QString m_header;
int m_index;
};
static const int NUMBER_COLUMNS = 1;
static TreeColumn s_columns[NUMBER_COLUMNS];
TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent)
{
parentItem = parent;
itemData = data;
}
TreeItem::~TreeItem()
{
qDeleteAll(childItems);
}
TreeItem *TreeItem::parent()
{
return parentItem;
}
TreeItem *TreeItem::child(int number)
{
return childItems.value(number);
}
int TreeItem::childCount() const
{
return childItems.count();
}
int TreeItem::childNumber() const
{
if (parentItem)
return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
return 0;
}
int TreeItem::columnCount() const
{
return itemData.count();
}
QVariant TreeItem::data(int column) const
{
return itemData.value(column);
}
bool TreeItem::setData(int column, const QVariant &value)
{
if (column < 0 || column >= itemData.size())
return false;
itemData[column] = value;
return true;
}
bool TreeItem::insertChildren(int position, int count, int columns)
{
if (position < 0 || position > childItems.size())
return false;
for (int row = 0; row < count; ++row)
{
QVector<QVariant> data(columns);
TreeItem *item = new TreeItem(data, this);
childItems.insert(position, item);
}
return true;
}
bool TreeItem::removeChildren(int position, int count)
{
if (position < 0 || position + count > childItems.size())
return false;
for (int row = 0; row < count; ++row)
delete childItems.takeAt(position);
return true;
}
bool TreeItem::insertColumns(int position, int columns)
{
if (position < 0 || position > itemData.size())
return false;
for (int column = 0; column < columns; ++column)
itemData.insert(position, QVariant());
foreach (TreeItem *child, childItems)
child->insertColumns(position, columns);
return true;
}
ControlTreeView::ControlTreeView(QObject *parent) :
QAbstractItemModel(parent)
{
QStringList headers;
s_columns[ControlTreeView::eCOLUMN_FILENAME].m_header = QObject::tr("File");
s_columns[ControlTreeView::eCOLUMN_FILENAME].m_index = 0;
for (unsigned int index = 0; index < NUMBER_COLUMNS; index++)
headers.append(s_columns[index].m_header);
QVector<QVariant> rootData;
foreach (QString header, headers)
rootData << header;
m_rootItem = new TreeItem(rootData);
}
ControlTreeView::~ControlTreeView()
{
delete m_rootItem;
}
int ControlTreeView::columnCount(const QModelIndex & parent) const
{
return NUMBER_COLUMNS;
};
TreeItem *ControlTreeView::getItem(const QModelIndex &index) const
{
if (index.isValid())
{
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if (item) return item;
}
return m_rootItem;
}
int ControlTreeView::rowCount(const QModelIndex &parent) const
{
TreeItem *parentItem = getItem(parent);
return parentItem->childCount();
}
Qt::ItemFlags ControlTreeView::flags(const QModelIndex &index) const
{
//if (!index.isValid())
// return 0;
//return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled;
Qt::ItemFlags defaultFlags = Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (index.isValid())
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
else
return Qt::ItemIsDropEnabled | defaultFlags;
}
QModelIndex ControlTreeView::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid() && parent.column() != 0)
return QModelIndex();
TreeItem *parentItem = getItem(parent);
TreeItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex ControlTreeView::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
TreeItem *childItem = getItem(index);
TreeItem *parentItem = childItem->parent();
if (parentItem == m_rootItem)
return QModelIndex();
return createIndex(parentItem->childNumber(), 0, parentItem);
}
QVariant ControlTreeView::data(const QModelIndex & index, int role) const
{
if (!index.isValid())
return QVariant();
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
{
TreeItem *item = getItem(index);
return item->data(index.column());
}
break;
case Qt::DecorationRole:
{
if (index.column() == 0)
{
if (!index.parent().isValid()) // Only decorate for
{
//QString file = m_jobList->GetJobSrcFileName(index.row());
//if (!file.isEmpty())
// return IconCache::Get().Load(file);
}
}
}
break;
}
return QVariant();
}
bool ControlTreeView::setHeaderData(int section, Qt::Orientation orientation,
const QVariant &value, int role)
{
if (role != Qt::EditRole || orientation != Qt::Horizontal)
return false;
bool result = m_rootItem->setData(section, value);
if (result)
emit headerDataChanged(orientation, section, section);
return result;
}
QVariant ControlTreeView::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return m_rootItem->data(section);
return QVariant();
}
QStringList ControlTreeView::mimeTypes () const
{
QStringList mimeTypes;
mimeTypes += "text/uri-list";
mimeTypes += "text/conversion-job-tree";
return mimeTypes;
}
QMimeData *ControlTreeView::mimeData(const QModelIndexList &indexes) const
{
qDebug() << __FUNCTION__;
QMimeData *mimeData = 0;
// If the window is out off focus a file is dragged from outside of the app
// This is not normal behaviour as this function should not be call if
// the drag comes from outside of the app (??).
mimeData = new QMimeData();
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
foreach (QModelIndex index, indexes) {
if (index.isValid() && !index.parent().isValid())
{
stream << index.row();
}
else
if (index.parent().isValid())
stream << -1;
}
mimeData->setData("text/conversion-job-tree", encodedData);
return mimeData;
}
Qt::DropActions ControlTreeView::supportedDropActions() const
{
return Qt::CopyAction;
}
bool ControlTreeView::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent)
{
qDebug() << __FUNCTION__;
if (action == Qt::IgnoreAction)
return true;
bool success = false;
if (action == Qt::CopyAction)
{
if (data->hasFormat("text/uri-list"))
{
QList<QUrl> urls = data->urls();
for (int i = 0; i < urls.size(); ++i)
{
QString file = urls[i].toLocalFile();
if (file != "")
{
// Check if the file is already in the table
int insertRow = -1;
if (parent.isValid())
insertRow = parent.row();
if (insertRow == -1)
if (row == -1)
insertRow = m_rootItem->childCount();
else
insertRow = row;
insertRows(insertRow, 1, QModelIndex());
setData(index(insertRow, s_columns[ControlTreeView::eCOLUMN_FILENAME].m_index), file, Qt::EditRole);
success = true;
}
}
}
else
{
// Different MineData used for drop tree items
if (data->hasFormat("text/conversion-job-tree"))
{
// Only drop on a job
if (parent.isValid() && parent.parent().isValid())
return false;
int insertRow = -1;
if (parent.isValid())
insertRow = parent.row();
if (insertRow == -1)
if (row == -1)
insertRow = m_rootItem->childCount();
else
insertRow = row;
QByteArray encodedData = data->data("text/conversion-job-tree");
QDataStream stream(&encodedData, QIODevice::ReadOnly);
int srcRowIndex = -1;
while (!stream.atEnd()) {
stream >> srcRowIndex;
}
// Exit if the source is not valid
if (srcRowIndex == -1)
return false;
if (srcRowIndex < insertRow)
{
insertRow--;
if (insertRow < 0)
insertRow = 0;
}
if (srcRowIndex == insertRow)
return false;
// Remove the original raw
removeRows(srcRowIndex,1);
// Insert a new raw
insertRows(insertRow, 1, QModelIndex());
//setData(index(insertRow, s_columns[ConversionJobTreeViewCtrl::eCOLUMN_FILENAME].m_index), m_jobList->At(insertRow)->GetBaseSrcFileName(), Qt::EditRole);
return success;
}
}
}
else
success = false;
return success;
}
bool ControlTreeView::insertRows(int position, int rows, const QModelIndex &parent)
{
TreeItem *parentItem = getItem(parent);
bool success;
beginInsertRows(parent, position, position + rows - 1);
success = parentItem->insertChildren(position, rows, m_rootItem->columnCount());
endInsertRows();
return success;
}
bool ControlTreeView::removeRows(int position, int rows, const QModelIndex &parent)
{
TreeItem *parentItem = getItem(parent);
bool success = true;
beginRemoveRows(parent, position, position + rows - 1);
success = parentItem->removeChildren(position, rows);
endRemoveRows();
return success;
}
bool ControlTreeView::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role != Qt::EditRole)
return false;
TreeItem *item = getItem(index);
bool result = item->setData(index.column(), value);
if (result)
emit dataChanged(index, index);
return result;
}
I am coding a Fibonacci sequence in Eclipse and this is my code-
public class FibonacciAlgorithm {
private int a = 0;
private int b = 1;
public FibonacciAlgorithm() {
}
public int increment() {
int temp = b;
b = a + b;
a = temp;
return value;
}
public int getValue() {
return b;
}
}
It is showing an error in the return value; line saying value cannot be resolved to a variable. I don't see any other errors.
Where is value defined? You return something that was not defined anywhere.
You don't have a "value" defined, this is your error. I don't remember the thing exactly, but I think you don't need a and b, I found this in my code archive, hope it helps.
public class Fibonacci
{
public static long fibo(int n)
{
if (n <= 1) return n;
else return fibo(n - 1) + fibo(n - 2);
}
public static void main() {
int count = 5; // change accordingly, bind to input etc.
int N = Integer.parseInt(count);
for (int i = 1; i <= N; i++)
System.out.println(i + ": " + fibo(i));
}
}
In case you want to stay with your own code, try returning "b" as value.
Your method is returning an int variable so you would have to define and return value as an int
I am not sure what you trying to do.
If you have "getValue" method I think "increment" method should be void.
When you want current Fibonacci value use "getValue" method.
public class FibonacciAlgorithm {
private int a = 0;
private int b = 1;
public FibonacciAlgorithm() {
}
public void increment() {
int temp = b;
b = a + b;
a = temp;
}
public int getValue() {
return b;
}