I have such queue:
boost::lockfree::spsc_queue<orders_log, boost::lockfree::capacity<8192>> futOrdersUpdates;
My problem is that sometimes I deque same item several times. I've added some troubleshoot code:
while (bool dequeued = futOrdersUpdates.pop(entryItem) || !endOfTransaction)
{
if (!dequeued) {
dequeueLoger.Debug("no items, try again");
continue;
} else {
if (lastRev != 0 && entryItem.replRev == lastRev) {
dequeueLoger.Debug("duplicate item!");
}
lastRev = entryItem.replRev;
}
// further processing
The idea is - if endOfTransaction flag is not set, I should "spin", otherwise I can exit if queue is empty.
In logs I found strange things:
"no items, try again" - is NEVER appear
"duplicate item!" - IS appear.
Expected behavior:
"no items, try again" should appear sometimes - when queue is empty but endOfTransaction flag is not set
"duplicate item!" should NEVER appear
The question is - if i'm "dequee" spsc_queue correctly? Any bugs in my code?
We can't possibly know why you are getting duplicates, because we have no idea how you fill replRev. It could be a data race right there (I hope you don't do lastRev+1, e.g.).
Note that you likely never get "No items try again" because the loop is skipped entirely, e.g.:
while (bool dequeued = foo())
{
assert(dequeued); // can never be false here!
}
will never even enter the loop.
The reason you get duplicates is because you say
bool dequeued = futOrdersUpdates.pop(entryItem) || !endOfTransaction;
As you know (see your comment) this forces dequeued to be true even if no item was dequeued, because endOfTransaction has not been set yet.
The value of entryItem is unspecified at that time - but likely just contains the previous value, leading to the "duplicate" message.
For a nice demo using spsc_queue I recently gave, see this answer: Dynamic generation & safe usage of spsc_queues
Related
I have a list, each element of which contains an inner list.
I need to get an element of the outer list, in which the specified condition is fulfilled for the inner list at least once.
I wrote code like this:
outerList?.find {
!it.items.isNullOrEmpty() && it.items?.any { item ->
item.isVisible == visibility &&
item.progress == currentProgress
} == true
}?.let { outerItem ->
currentItem = outerItem
// here some logic
} ?: run {
currentItem = null
// here some logic
}
But I'm not sure if this code is efficient. Perhaps you should use sequences instead of a list?
Can you please tell me which solution will be the most efficient in terms of execution time and memory consumption for my case?
A sequence isn't going to help here, because you are only performing one operation on the outer list, and one operation on the inner list.
Your !it.items.isNullOrEmpty() check is entirely redundant to the ?.any you follow it up with, so you can remove that. Perhaps the cleanest way to write this would be:
outerList?.find {
it.items.orEmpty().any { item ->
item.isVisible == visibility && item.progress == currentProgress
}
}
Never do this: ?.let { ... } ?: run { }. Aside from being very poor for readability, it is error-prone. If you accidentally return null from the let block, the run block will also be run unexpectedly.
When running my C++/Qt5 program under gdb I experienced what seems like an impossibility:
while(totalAvailable > (sizeof(quint32)+sizeof(quint16))){
if(nullptr!=c){
// POINT-A
qDebug()<<rct<<"Courier message with ID "<<octomy_message_type_int<<" was received with name "<<c->getName()<<" and "<<bytesAvailable<<" bytes available";
const quint16 bytesSpent=c->dataReceived(*ds, bytesAvailable);
const int left=bytesAvailable-bytesSpent;
totalAvailable-=bytesSpent;
if(left>=0){
if(left>0){
ds->skipRawData(left);
totalAvailable-=left;
}
else{
// POINT-B
qDebug()<<rct<<"LOLBOB";
}
}
else{
qWarning()<<"BAR";
return;
}
}
else{
qWarning()<<"FOO";
return;
}
}
In short, when I step from //POINT-A to //POINT-B everything is as expected, but as soon as I step past //POINT-B debugger jumps up to the first line of the program (while statement). But there are no break or continue or other flow-altering statements in the code. How is this possible?
I have tried rebuilding my code from scratch to eliminate a bogus linkage or similar problems, but the bug is reproducible still.
Any input is welcomed.
At POINT-B, you are inside an else, which is inside an if, which is inside an if. Once this else is done, there is nothing more to do in the whole tree.
Where would you expect the pointer to jump to??
Technically, it would go to the closing bracket two lines behind POINT-B, then to the closing bracket three lines behind POINT-B, and then to closing bracket eight lines behind POINT-B, and then to the closing bracket at the very end. All those do nothing, so they are skipped.
Take a paper and pencil, and diagram the logical flow of this chunk of code.
You will make a surprising discovery that the only statement that could possibly execute, after the statement you marked "POINT B", is the condition at the beginning of the while loop. After executing the "POINT B" statement, there are no more statements to execute in the body of the loop, so execution winds back to the while condition, for the next iteration.
Basically the loop just re-iterates. I believe it is functioning as it is supposed to. From Point-A the control goes like such:
If no.1 (Point-A) -> If no.2 -> Else corresponding to If no.3 -> back to end of If no.2 -> back to end of If no.1 -> back to end of while loop.
As the loop is over, the execution checks the loop's condition, (if it is satisfied) re-iterates, and eventually you reach Point-A again.
while()
{
if() // If no.1
{
// Point-A *****************************
if() // If no.2
{
if() // If no.3
{
}
else()
{
// Point-B *****************
}
}
else
{
}
}
else
{
}
}
To improve debugging and readability, do not keep nesting if blocks or loops - It is very hard to trace the execution.
Look if you write it this equivalent way:
while(totalAvailable > (sizeof(quint32)+sizeof(quint16))){
if(nullptr==c){
qWarning()<<"FOO";
return;
}
// POINT-A
qDebug()<<rct<<"Courier message with ID "<<octomy_message_type_int<<" was received with name "<<c->getName()<<" and "<<bytesAvailable<<" bytes available";
const quint16 bytesSpent=c->dataReceived(*ds, bytesAvailable);
const int left=bytesAvailable-bytesSpent;
totalAvailable-=bytesSpent;
if(left<0){
qWarning()<<"BAR";
return;
}
if(left>0){
ds->skipRawData(left);
totalAvailable-=left;
}
else{
// POINT-B
qDebug()<<rct<<"LOLBOB";
}
}
Had a new problem with the while function. As easy as it sounds, I still can't wrap my head around it.
Like my last program, this one closes unexpectedly after the correct and wrong messages.
I want this to loop after entering a number, so that the program won't stop.
Thanks for the help, if any.
#include <iostream>
using namespace std;
int main()
{
int X = 0; //setting the first variable
int num; //setting the second
while (X == 0) //this should happen whenever X is equal to 0
{
cout << "Type a number bigger than 3. "; //output
X++; //This should increase X, so that the next while function can happen
}
while (X == 1) //again, since I increased x by one, (0+1=1 obviously) this should happen
{
cin >> num; //standard input
if (num > 3) //if function: if num is bigger than three, then this should happen
{
cout << "Correct! Try again!" <<endl; //output
X--; //Here I'm decreasing x by one, since it was 1 before, now it becomes 0. This should make the "while (X == 0)" part happen again, so that another number bigger than three can be entered
}
if (num <= 3) //if function: if num is lesser than or equal to 3, this should happen
{
cout << "Wrong! Try again!" <<endl; //output
X--; //This is supposed to work like the "X--;" before, repeating the code from "while (X==0)"
}
}
}
now it becomes 0. This should make the "while (X == 0)" part happen again
Nope. While loops don't magically take effect at any point during execution of the program. You only enter a while loop when you've reached it from code above. Programs are executed top-to-bottom, generally.
You would need a loop around the entire program if you want to keep going round and round. Those whiles you have now should probably be ifs.
Merge the two while loops into one, while(true).
Put each previous while body into an if state with the clause from the old while in it.
while(true) {
if (X==0) {
// the X==0- case
} else if (X==1) {
// the X==1 case
}
}
in order to end your loop, do a break;.
You have to think of C++ programs as a sequence of instructions, like a recipe. while just means a loop: you check the condition. If true, you run the body. After running the body, you check only that condition again, and run the body if true. Whenever the condition is false at the start or end of the body of the while (the {} enclosed code after it), you end the loop and proceed to the next one.
The first loop runs, finishes, then the second loop runs in your code. Once the first loop exits, you do not go back into it just because the condition becomes true.
Understanding flow control is one of the "hard" steps of learning to program, so it is ok if you find this tricky.
There are many improvements you can do your code beyond getting it working -- there is, actually, little need for X at all. But baby steps! Once you get it working, you can ponder "how could I remove the variable X?".
Before making such fundamental changes to your program, you should get it working, and save a copy of it so you can "go back" to the last working version.
You want to wrap all that code in it's own while loop:
while (true /* or something */)
{
while (X == 0) //this should happen whenever X is equal to 0
{
// ...
}
At least put your second while loop inside the first one to get it working as intended. Otherwise your program has no reason to go back again.
Nevertheless it's not a good design.
My program simulates a video store. In my list there are multiple copies of some videos. If I try to rent a video and the first copy of that video in the list is already rented, my program fails to continue checking to see if the other copies are available (a film is available if custId is '0000'). Take a look at the text file from where the list gets its members for a better understanding of what i'm describing:
Could anyone take a look and let me know if they spot an issue? Any help is appreciated, thanks.
Code from main
try
{
int index = 0;
bool found = false;
while (!found)
{
if (strncmp(filmId,filmList.getAt(index).number,6) == 0 && strncmp("0000",filmList.getAt(index).rent_id,5) == 0)//If that film is rented by NO customer
{
found = true;//customer can rent it
strcpy(newItem.number,filmId);//copy filmId into newItem
filmList.retrieve(newItem);//copy the struct in our orderedList with the same filmId/copy into newItem
filmList.remove(newItem);//delete the struct with same filmId/copy as newItem from the orderedList
strcpy(newItem.rent_id,custId);//update info in
strcpy(newItem.rent_date,rentDate);// newItem to show
strcpy(newItem.return_date,dueDate);// that it has been rented
filmList.insert(newItem);//put NewItem into list, effectivily replacing the removed item.
cout << "Rent confirmed!" << endl;
}
else
{
if (strncmp(filmId,filmList.getAt(index).number,6) > 0 || strncmp("0000",filmList.getAt(index).rent_id,5) > 0)
{
++ index;
}
else
{
throw string ("Not in list");
}
}
}
}
catch (string s)
{
cout << "\n***Failure*** " << s << endl;
}
Let me know if more code is required from any other parts of the program.
Here's my best guess with the code provided.
Let's say we are looking up 101001Casablanca, therefore I'm assuming filmId = "101001Casablanca". Also, assume the 101001Casablanca is checked out to customer 0001. We are comparing the first 6 characters of filmId to filmList.getAt(index).number, which I'm going to assume is at the very least "101001". This passes, but since it is checked out the second condition fails.
In the else we check the same strings in the first condition and still get 0 returned from strncmp which is false. The second condition is also false since strncmp("0000", "0001", 5) is -1. Therefore we go to the final else which throws.
If you are only checking string equality with strncmp, remember that it can return -1, therefore check if equal or not equal to 0.
The error I'm getting is error: expected ' ; ' before ' { ' token
I tried fixing the code by adding ; after if (thisisanumber==5) as well as after else (thisisanumber!=5). While this solves the first error it creates another error that says error: ' else ' without a previous ' if '. I'd really love to know what error I've made in writing the code, thanks.
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int thisisanumber;
cout<<"Whats the Password?: ";
cin>> thisisanumber;
cin.ignore();
if (thisisanumber==5) {
cout<<"You've discovered the password! Wow, you're a genious you should be proud./n";
}
else (thisisanumber!=5) {
cout<<"You've failed in knowing the password and therefore cannot enter, leave and do not come back. Goodbye!/n";
}
cin.get();
}
You're missing a keyword if:
else if (thisisanumber!=5) {
^^
Alternately, since the opposite condition to thisisanumber == 5 is that thisisanumber is not 5, you don't need the condition:
else {
You don't need another condition as there are only two cases - just use else { ... } and it will catch all cases in which thisisanumber==5 is false.
The structure of an if statement is:
if (condition) { ... }
else if (another condition) { ... }
// ... more conditions
else { ... all cases in which no previous condition matched end up here ... }
... but the else if and else parts are always optional.
What happens is the compiler looks at the following:
else (thisisanumber!=5) {
and thinks to itself:
"OK, here's else. Is the next token if? No. Ok, so this is an else clause, and the next thing is what to do in the else-case. Is the next token {? No. Ok, so in the else-case, we execute a single statement, instead of a block. Is the next token (? Yes. Ok, so our statement is wrapped in parentheses... [insert here: the rest of the thought process for interpreting an expression that's wrapped in parentheses] Ok, there's the matching ). Whew. Now let's just match up the ; for this statement... wait, what's this? A {! That's not right."
The compiler is reading the code one token at a time, left to right. It does not report an error at the point where, in a logical sense that humans understand, the error actually is. It reports an error at the point where, by reading the code one token at a time, left to right, it is first able to detect that something is wrong.
It would be legal to write else (thisisanumber!=5);. That would mean "if the number is not equal to 5 (because the if test failed), then check if the number is not equal to 5, and do nothing with the result of that comparison". Meaningless, but legal. It would also be legal to write else if (thisisanumber!=5) {...}, which is presumably what you meant. That would mean "if the number is not equal to 5 (because the if test failed), and the number is not equal to 5, then do this stuff inside the {}". But this is redundant: given that something is not equal to 5, it is guaranteed to be not equal to 5, so there is no point in specifying the test twice. So we should just write else {...}.
"else" is really a shorter word for "otherwise", and has that purpose in C++ as well.