Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
volatile actually does not make any memory ordering guarantees at all in C/C++. There's a sort of implicit understanding that the compiler will perform the operation "normally", i.e. using some obvious load/store instructions, and most architectures do make at least some weak causality guarantees about the ordering of normal loads and stores. But volatile itself does not make these guarantees.

C1x and C++11 do provide special atomic types that make real memory ordering guarantees, although AFAIK they're not really properly implemented anywhere quite yet.

ETA: Oh, I forgot: there are some weak intra-thread guarantees involving volatile operations, but they're mostly useless for doing inter-thread communication: they just constrain the compiler from reordering the volatile operations, but the processor is not constrained unless the volatile operation actually does something like memory-mapped I/O.

rjmccall fucked around with this message at 02:21 on Oct 24, 2011

Adbot
ADBOT LOVES YOU

shrughes
Oct 11, 2008

(call/cc call/cc)

Rocko Bonaparte posted:

I have a question about boost multithreading and variables. I have some threads looping on their own bools. When they go false, I exit the thread.

Then you're doing something wrong. How have you set things up such that your threads are not spinning just on that variable and eating CPU? How have you set things up so that you'll always get around to checking that boolean in a reasonable amount of time?

Rocko Bonaparte posted:

I think sometimes this isn't working. What I've seen in the long past last time I dealt with this was that the value was getting cached, so one thread's true was another thread's false. What is there in boost's own stuff to eliminate this kind of problem. I assume there's something more robust than just declaring all the relevant stuff volatile, and I don't think mutexes are going to protect me from that. Wouldn't a mutex just ensure at one time only one thread is touching a representation of the variable?

volatile won't do anything and is totally unnecessary. If you're doing an empty spinloop around a boolean then you want to use a condition variable: http://www.boost.org/doc/libs/1_35_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref

You're probably not doing that, I imagine you've got some thread doing something in a loop and somebody else can shut it down.

There are bugs that could be resolved by putting the access of the boolean in a mutex. Certainly there is a risk of valgrind errors, otherwise.

Another probable source of bug is that you've got some blocking operation in the middle of the loop, and so you never get to the boolean check and thus never exit the thread. I'm not too familiar with the best practices of interrupting blocking I/O but I think the way you'd do that is to send a signal to the thread and checking for the shutdown condition in the case of EINTR. But there are some system calls which block and recover from EINTR, aren't there? So that must be wrong...

Edit: Yeah, how in the world do people shutdown threads that use blocking I/O and blocking pthread operations like pthread_mutex_lock which resume waiting for the lock when a signal happens?

shrughes fucked around with this message at 02:51 on Oct 24, 2011

Brecht
Nov 7, 2009

shrughes posted:

Edit: Yeah, how in the world do people shutdown threads that use blocking I/O and blocking pthread operations like pthread_mutex_lock which resume waiting for the lock when a signal happens?
If I understand you correctly, it's the poison pill idiom:
code:
void main_loop() {
    lock thread_mtx
    running = true
    while running {
        unlock thread_mtx
        resource = blocking_resource_call()
        relock thread_mtx
        if !running, break
        else, operate on resource
    }
}

void stop() {
    lock thread_mtx
    running = false
    poison_pill(resource) // blocking_resource_call returns
}

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

shrughes posted:

Then you're doing something wrong. How have you set things up such that your threads are not spinning just on that variable and eating CPU? How have you set things up so that you'll always get around to checking that boolean in a reasonable amount of time?

The thread can be interrupted too but I consider that an abnormal termination. Some of the threads really do just spin and spin in this case, and others in the same setup are more like consumers, so I do use condition variables for them. In those cases, the stop signal I transmit also signals the condition variable to finish a pass on the loop.

Even with interruption, I can still get screwed with a long, blocking operation. I think Boost's interrupt only will trigger on certain points so it won't interrupt at any given spot of code.

Edit: Well I found the immediate source of trouble for me, and it actually had to do with the threads that had a condition variable. :( I basically had to create a predicate operator for them to double check that stop boolean I had given them. It looks like the main run loop would enter the wait() block before they'd get the bool change. I also made sure the Stop() method that was setting the bool is messing with the bool inside the lock. Before, it was just grabbing the lock so it could feed it to the condition variable to do a notify. That in itself didn't fix it.

I'm still not sure what to think of that. I think my original question is still farting around in there. This wasn't ever an issue to me until I was playing with a system that had two sockets, versus just multiple cores on one socket. The extra lag from the geography of being split apart was enough to cause all hell to break loose.

Rocko Bonaparte fucked around with this message at 14:48 on Oct 24, 2011

krisis
Oct 25, 2003

i have a light case of asparagus.

shrughes posted:

Edit: Yeah, how in the world do people shutdown threads that use blocking I/O and blocking pthread operations like pthread_mutex_lock which resume waiting for the lock when a signal happens?

The regular unix system calls (read, write, open, etc.) will not restart unless you register the signal handler with the SA_RESTART flag. So, you can write those off with checking for EINTR (and checking for a flag variable when you succeed, since interrupting a read that already has some data will return successful with the partial read).

The pthread calls get a little more hairy. You can use pthread_cancel from the signal, but that requires that you wait on a condition variable instead of locking a mutex, since the pthread_mutex_lock function isn't a cancellation point. It also involves having to use the pthread_cleanup_push macro which a really bad interface.

I havn't tested this, but using sigsetjmp and siglongjmp to jump out of the wait might also work. It looks reasonable if you don't want to sprinkle pthread_testcancel and pthread_cleanup_push calls all over your compute bound function that needs to do cleanup.

TasteMyHouse
Dec 21, 2006
I'm looking for a tool that will take my vcxproj or sln file and spit out a makefile that works with gcc on Linux. I found winemaker, which sort of does what I want except it is designed for wine, so the makefiles it spits out use "winegcc" instead of regular gcc. If need be I can just write a script to correct all the makefiles it spits out, but I'd rather not do that if I don't have to. Does anyone know of a more general purpose tool for this?

Paniolo
Oct 9, 2007

Heads will roll.

TasteMyHouse posted:

I'm looking for a tool that will take my vcxproj or sln file and spit out a makefile that works with gcc on Linux. I found winemaker, which sort of does what I want except it is designed for wine, so the makefiles it spits out use "winegcc" instead of regular gcc. If need be I can just write a script to correct all the makefiles it spits out, but I'd rather not do that if I don't have to. Does anyone know of a more general purpose tool for this?

CMake can generate both Visual C++ projects and makefiles. It's not quite what you're asking for, because you'll need to do the extra step of writing CMake scripts instead of just using your Visual C++ projects as input.

TasteMyHouse
Dec 21, 2006

Paniolo posted:

CMake can generate both Visual C++ projects and makefiles. It's not quite what you're asking for, because you'll need to do the extra step of writing CMake scripts instead of just using your Visual C++ projects as input.

Yeah, I think I'm just going to hand-write makefiles. The reason I ask is because I have dozens of solutions, some of which have dozens of projects, and I want to port them as quickly as possible. after spending a day looking for pre-built automated solutions, I've decided to just suck it up and start writing makefiles :(

dereekb
Nov 7, 2010

What do you mean "error"?
Alright, here's an easy question that probably has a very simple solutions:

I have two classes, Customer and Transaction that both implement each-other. The solution fails to compile however, since one class or the other isn't declared when the header file is compiled...

So I end up with the compiler error:

code:
Customers.h:97: `Transaction' was not declared in this scope
Customers.h:97: template argument 1 is invalid
Customers.h:97: ISO C++ forbids declaration of `Transactions' with no type
...or the customers class completely failing to be created. :v:

Is there a way to define the class as a prototype/dummy ahead of time like with functions, or what is the best solution?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
If you just need to refer to one class somewhere in the definition of another, you can forward-declare classes like so:

code:
class Transaction;
Note that this class is incomplete until its definition has been processed, which restricts what you can do with the type pretty heavily — among other things, you can't inherit from an incomplete class, which happens to make it impossible to even try to make two classes "implement" each other.

dereekb
Nov 7, 2010

What do you mean "error"?
Perfect, exactly what I needed. Thanks!

Edit:

Actually, still have one problem dealing with how to set up the function correctly, because I currently get this message:

code:

Info.h:33: no matching function for call to `Customer::addTransaction(Transaction* const)'
Customers.h:93: candidates are: void Customer::addTransaction(const Transaction&)

I have the Transaction constructor set up like this:

code:
Transaction(string Info, Type T, Customer* c = 0, double a = 0) : TransInfo(Info), TransType(T), Person(c), Value(a)
	{
		c->addTransaction(this);
	}
This is the addTransaction function in the Customer's file:

code:
void addTransaction(const Transaction& t){ Transactions.push_back(t); }
Now, (aside from the other problems I realize is wrong with this...), what is the correct way to pass the Transaction object to the Customer object, or get this transaction into a Vector defined in the Customer object?

dereekb fucked around with this message at 05:29 on Oct 25, 2011

DeciusMagnus
Mar 16, 2004

Seven times five
They were livin' creatures
Watch 'em come to life
Right before your eyes
code:
Transaction(string Info, Type T, Customer* c = 0, double a = 0) : TransInfo(Info), TransType(T), Person(c), Value(a)
	{
		c->addTransaction(*this);
	}
You're passing a pointer to a Transaction object to a function that needs an Transaction object because it takes a reference to a Transaction object. Dereferencing this gives you exactly that.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
addTransaction wants a reference to a transaction, but this is a pointer. You should either make addTransaction take a pointer or pass it *this (which produces an l-value to which the reference can bind, but which is otherwise functionally equivalent).

Which you should do is something that people have a lot of opinions about.

dereekb
Nov 7, 2010

What do you mean "error"?
Right, that makes sense, and better yet, compiles. Pointer syntax is not something I'm too fond of yet, hah. :)

Thanks!

raminasi
Jan 25, 2005

a last drink with no ice
Writing a function that has default values but segfaults when you actually call it using them seems like rather poor design.

Modern Pragmatist
Aug 20, 2008
So I have a function that assigns certain items to a group based on certain properties, then passes the remaining ungrouped items back through the function recursively until all items are assigned to groups. I'm currently doing this via the following:

code:
void group_items(double *items, int *group, int *skip, size_t nItems, int groupNum) {

    int i, remaining = 0;

    for (i=0; i<nItems; i++) {
        /* Ignore items that already belong to a group */
        if (skip[i]) { continue; }

        /* Otherwise see if it should be added to the current group */

        if (add_to_group) {
            group[i] = groupNum;
            skip[i] = 1;
        } else {
            remaining ++;
        }
    }

    if (remaining) {
        group_items(items,props,group,skip,nItems,groupNum + 1);
    }
}
So basically I just have a skip vector that indicates whether an item is still available for assignment to a group or not.

Is there a better way to do this? I'm dealing with vectors that are often 65000+ elements and I feel like looping through all of those just looking for ones to skip is hogging a lot of resources.

DeciusMagnus
Mar 16, 2004

Seven times five
They were livin' creatures
Watch 'em come to life
Right before your eyes
One thing I can suggest is to put the item, group, and skip into a struct, but that's just to keep things together. Also, make i size_t. If you insist on incrementing remaining instead of just assigning 1, I recommend making it a size_t as well.

You could make a list of groups and, instead of assigning a group to an item, assign an item to a group. Your structure that stores ungrouped items would need to be able to actually shrink instead of being an array (otherwise you have the same problem).

I would need to know more about the nature of the data and it's grouping in order to make good recommendations. What are the parameters for determining grouping? What is needed to decide an item's group?

seiken
Feb 7, 2005

hah ha ha
Uh, post the code that determines the value of add_to_group. If subsequent groups don't somehow depend on what items were put in earlier groups, you can easily do the whole thing in one pass with no recursion...

yippee cahier
Mar 28, 2005

Finally got around to watching that modern C++ webcast from Build. I come from a C background and always just used python to get stuff done at a higher level, skipping C++ because it seemed unnecessarily complex for what I wanted to do. I think I'm beginning to get it now, though.

I know the standard just came out, but does anyone have a recommendation for learning C++ starting at C++11? I don't want to buy the classic texts on the language only to learn something passe or dangerous.

TasteMyHouse
Dec 21, 2006

sund posted:

Finally got around to watching that modern C++ webcast from Build. I come from a C background and always just used python to get stuff done at a higher level, skipping C++ because it seemed unnecessarily complex for what I wanted to do. I think I'm beginning to get it now, though.

I know the standard just came out, but does anyone have a recommendation for learning C++ starting at C++11? I don't want to buy the classic texts on the language only to learn something passe or dangerous.

Learning C++11 right now will not help you out in any practical way, as no compilers support it fully yet and if you're doing anything with C++ you're going to have to deal with C++03 code at some point anyway.

Learn C++03 and C++11 at the same time. This will help you understand the "why" behind a lot of the C++11 features better, anyway.

Dr Monkeysee
Oct 11, 2002

just a fox like a hundred thousand others
Nap Ghost

dereekb posted:

I have the Transaction constructor set up like this:

code:
Transaction(string Info, Type T, Customer* c = 0, double a = 0) : TransInfo(Info), TransType(T), Person(c), Value(a)
	{
		c->addTransaction(this);
	}

GrumpyDoctor posted:

Writing a function that has default values but segfaults when you actually call it using them seems like rather poor design.

Uh... I think this needs to be re-emphasized.

Dicky B
Mar 23, 2004

sund posted:

I don't want to buy the classic texts on the language only to learn something passe or dangerous.
You won't. Don't worry about it too much.

TasteMyHouse
Dec 21, 2006
I have a feeling that this should just go in the coding horrors thread, but I figured I'd see if y'all had anything to say about this.

At three separate places in this particular project that I'm porting to Linux from VC6, this pattern is employed:

code:

if(complicated_conditional_expression_with_no_side_effects)
{
    int x=x;
}

What the hell are they trying to do here?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

TasteMyHouse posted:

What the hell are they trying to do here?
I'd guess they were wanting a conditional breakpoint - "int x=x;" provides a line you can activate a breakpoint on, and, being inside the conditional block, it will only activate if the condition is met. I've done that same sort of construct several times while debugging (though I usually do int break=1;). Leaving it in the code afterwards seems a bit off though. Does the complicated conditional expression look like something that might be for that purpose?

TasteMyHouse
Dec 21, 2006
code:
 
if(currentMB->posX == 0/16*16 && currentMB->posY == 0/16*16) { // 221   315
Here's one of them. I don't know. The comment does not help.

Modern Pragmatist
Aug 20, 2008

DeciusMagnus posted:

I would need to know more about the nature of the data and it's grouping in order to make good recommendations. What are the parameters for determining grouping? What is needed to decide an item's group?

seiken posted:

Uh, post the code that determines the value of add_to_group. If subsequent groups don't somehow depend on what items were put in earlier groups, you can easily do the whole thing in one pass with no recursion...

I went ahead and pasted the entire function here

Basically it's an implementation of QT clustering. The basic idea is this:

1) Start with a particular point and add the closest points until the distance between any two points in the group exceeds the specified threshold.
2) Do this for each of the points.
2) Check the cardinality to determine which one is the largest group.
3) Keep the largest group and repeat this process for all remaining items.

In the function, D is precomputed distances between all points.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

TasteMyHouse posted:

code:
 
if(currentMB->posX == 0/16*16 && currentMB->posY == 0/16*16) { // 221   315
Here's one of them. I don't know. The comment does not help.
The comment is probably the values of posX and posY at some point that was interesting.

TasteMyHouse
Dec 21, 2006
what's the deal with 0/16*16 though?

tractor fanatic
Sep 9, 2005

Pillbug

TasteMyHouse posted:

what's the deal with 0/16*16 though?

He was probably playing with formulas with debugging with that breakpoint.

DeciusMagnus
Mar 16, 2004

Seven times five
They were livin' creatures
Watch 'em come to life
Right before your eyes

Modern Pragmatist posted:

I went ahead and pasted the entire function here

Basically it's an implementation of QT clustering. The basic idea is this:

1) Start with a particular point and add the closest points until the distance between any two points in the group exceeds the specified threshold.
2) Do this for each of the points.
2) Check the cardinality to determine which one is the largest group.
3) Keep the largest group and repeat this process for all remaining items.

In the function, D is precomputed distances between all points.

I would ask myself how acceptable the performance. You're solution will work and is fairly simple, but is it a prohibitively expensive implementation? There are probably better ways of doing this but I'd need to know where the worst performance is. For instance, as your ungrouped set gets smaller, the less efficient this approach gets. A linked list would allow you to remove points that are no longer candidates from the ungrouped list, but it has different overhead as well that needs to be taken into consideration. A linked list of arrays might be a good compromise for your ungrouped list. You could keep the array but rearrange it every time you group something so the ungrouped are contiguously clustered somewhere. You basically need a large dynamic list. See the following for a comparison of the performance of these: http://en.wikipedia.org/wiki/Dynamic_array#Performance

Line 14: Suggest making your counters size_t.
Line 45: This should be && not &.
Lint 72: Suggest using DBL_MAX from <limits.h>. Or set minjdiam to jdiam[0] and loop from 1 to nPoints.
Line 83: This should be || not |.

Modern Pragmatist
Aug 20, 2008

DeciusMagnus posted:

I would ask myself how acceptable the performance. You're solution will work and is fairly simple, but is it a prohibitively expensive implementation? There are probably better ways of doing this but I'd need to know where the worst performance is. For instance, as your ungrouped set gets smaller, the less efficient this approach gets. A linked list would allow you to remove points that are no longer candidates from the ungrouped list, but it has different overhead as well that needs to be taken into consideration. A linked list of arrays might be a good compromise for your ungrouped list. You could keep the array but rearrange it every time you group something so the ungrouped are contiguously clustered somewhere. You basically need a large dynamic list. See the following for a comparison of the performance of these: http://en.wikipedia.org/wiki/Dynamic_array#Performance

Line 14: Suggest making your counters size_t.
Line 45: This should be && not &.
Lint 72: Suggest using DBL_MAX from <limits.h>. Or set minjdiam to jdiam[0] and loop from 1 to nPoints.
Line 83: This should be || not |.

Ok great. Thanks for the advice. I'm just getting back into C after a long hiatus.

raminasi
Jan 25, 2005

a last drink with no ice
Do I need to set some flags to get boost::range (1.47) to work with C++11 lambdas? Or am I out of luck? (Or am I just doing this wrong?)
code:
boost::copy(vec | boost::adaptors::transformed([](int x) { return x * 2; }), std::back_inserter(out));
The errors are all about how boost can't figure out the result type of the lambda.

delta534
Sep 2, 2011
Define BOOST_RESULT_OF_USE_DECLTYPE as a macro before your boost includes to make c++11 lambdas work with boost::range

HipsLikeCinderella
Nov 8, 2006

I have very little C experience so I'm working on a little project but I've hit a speedbump at a very early stage. All I'm trying to do now read lines one at a time from a file and count how many I get. For some reason fgets is giving me nothing but null and I can't figure out why.. seems like I must be missing something very obvious. The file temp.txt is just a series of short (~1-6 char) strings, one per line.

code:
void operate(char *outFile)
{
	char line[257];
	char *tok = NULL;
	FILE *fptr, *ofptr;
	int count = 0;
	
	fptr = fopen("temp.txt", "r");
	if (fptr == NULL)
	{
		printf("Could not open temp. file for command processing, aborting..\n");
		exit(-1);
	}

        // First method - doesn't work
	// while (tok = fgets(line, MAX_LINE_LENGTH, fptr) != NULL) {
	// 	count++;
	// }
	
        // Second method - also doesn't work.
	while (fgets(line, 256, fptr) != NULL) 
	{
		count++;
		if (count > 100) 
		{
			exit(-1);
		}
	}

	ofptr = fopen(outFile, "w");
	if (fptr == NULL)
	{
		printf("Could not create output file, aborting..\n");
		exit(-1);
	}
	fprintf(ofptr, "Number of tokens: %d\n", count);
	fclose(ofptr);	
}

DeciusMagnus
Mar 16, 2004

Seven times five
They were livin' creatures
Watch 'em come to life
Right before your eyes
Nothing seems immediately wrong to me for why fgets fails. It fails either because it's the end of file or an error occurred. Test for an error with ferror, and if it returns true, use perror to output the associated error.

Also, the != operator will get evaluated before the =, meaning all you're assigning to tok is true or false. Don't forget to close fptr.

Captain Cappy
Aug 7, 2008

Runs fine for me using a C++ compiler. Are you sure you're editing the right temp.txt?

HipsLikeCinderella
Nov 8, 2006

Captain Cappy posted:

Runs fine for me using a C++ compiler. Are you sure you're editing the right temp.txt?

Well, I'm not familiar with how C does relative directories but I create the file temp.txt earlier in the program using a parser. All the files, including the sources/headers and the compiler are in the same directory.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Are you flushing the stream you're using to write to the file before you try reading it?

DeciusMagnus
Mar 16, 2004

Seven times five
They were livin' creatures
Watch 'em come to life
Right before your eyes
It depends on the implementation, but usually, with just a filename, you access from your current directory.

Adbot
ADBOT LOVES YOU

HipsLikeCinderella
Nov 8, 2006

Jabor posted:

Are you flushing the stream you're using to write to the file before you try reading it?

Haha thanks man, I'm an idiot.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply