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
OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
More of a platform-specific question, but on Windows/Linux, will using blocking file IO within a thread block the thread, or the entire process?

Adbot
ADBOT LOVES YOU

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

csammis posted:

On Windows it'll only block the thread. This is why you do blocking I/O or heavy processing in a thread other than the UI thread, so the UI remains responsive to input while blocking is happening.
This is actually for a game, all asset loads are deferable but I'm trying to get the IO operations offloaded to another thread so they don't cause framerate hiccups. Abstracting asynchronous IO is messier than abstracting threads and just using blocking IO operations in preload tasks.

I really don't care if the IO thread stalls. I do care if the rendering thread stalls!

OneEightHundred fucked around with this message at 02:25 on Jan 20, 2009

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
If it's simple and consistent enough, you could also cheat and use regular expressions.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Am I correct in assuming that the lifespan of a value used in an expression is the statement and that destructors will never be called until every operation in the statement happens? Or is there something else that determines destruction time for that?

Also, considering that some compilers pad up the size of empty structures, is it guaranteed that a class that extends an empty structure will NOT padded at the start? MSVC clearly doesn't, but I'm not sure if it's standardized or not.

OneEightHundred fucked around with this message at 17:35 on Sep 3, 2011

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

roomforthetuna posted:

Two comments on your code there - one, generally for every time you use a 'new' you should have a corresponding 'delete'
Or better yet, use auto_ptr/shared_ptr so the app doesn't leak memory every time you forget a delete or miss an exception.

RAII is probably the single most useful thing about C++ and it's best to understand it early.

OneEightHundred fucked around with this message at 04:20 on Sep 7, 2011

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Platform-specific fun stuff: It looks like if you allocate memory using "new", then Visual C++'s debugger will break it down as the type it was allocated as even if referenced through a parent type or void pointer. However, if it was created using a custom allocator (i.e. placement new), it only shows as the type of the pointer you're looking at.

Anyone know if there's a mechanism for producing the type-aware behavior with a custom allocator?

OneEightHundred fucked around with this message at 21:34 on Sep 27, 2011

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

pseudorandom name posted:

Types without a vtable can only possibly be one type which is known at compile time.
I'm pretty sure this isn't true, you just wind up getting a vptr after the vptr-less parent class's properties.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Rocko Bonaparte posted:

I heard you have to go through some hoops to make it poop out native code.
Not really, there's a setting which determines what kind of code it outputs (native, native+MSIL, MSIL-only, and some specializations of those) and that's pretty much it.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Plorkyeran posted:

Putting intermediate files on a ram disk can make linking a lot faster, but compiling is usually CPU-bound.
Compiles are massively sped up by having more CPUs/cores.

Links can strain CPU/RAM as well if you're using link-time code generation.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
You might be copying the full object when doing something, in the process copying the contents pointer and causing a double-free when the destination dies.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Any non-brain-damaged compiler is smart enough to just completely drop a conditional block if the condition const-folds to false, and will completely drop a function call if the function is inlined, does nothing, and the parameter passing is operation-free (i.e. no copies).

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Even if you're dealing with a compiler that can't do that, parameter lists enclosed in () only count as one parameter in macros. It looks kind of awkward but it works.

i.e.:
code:
#ifdef NDEBUG
#define DPRINTF(p) ((void)(0))
#else
#define DPRINTF(p) dprintf p
#endif

...

DPRINTF(("my format %i\n", 1));

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
What's the usual strategy for dealing with circular dependencies in inline functions that are in separate headers?

i.e. Header A defines some types and some inline functions that depend on some structures in header B, but the reverse is also true.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
I'm a bit fuzzy on how value lifetime works internally when you throw the value. In particular, how is it that you can catch a reference if the reference is to a value that was allocated in a stack frame that's destroyed before the catch block can do anything with it?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Paniolo posted:

edit: I did some poking around Visual C++, the way it handles it is that the value actually exists on the stack at the original call site.
I'm assuming by "call site" you mean the catch block?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Paolomania posted:

I'm taking it to mean that the data is still just floating there on the now-invalid stack frame of the code block that generated the exception (call-site referring to the instruction that generated the exception). Because you are only popping frames to the point of the catch block, you as the compiler writer can be sure that the exception's frame has not been overwritten. You might need to copy it aside at the point of the handler, because now the handler will potentially be making calls.
Yeah misread, I thought he meant that the copy is allocated on the stack at the catch site.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Shutdowns/cleanup should be waiting until all work threads have stopped, if you can't do that then at least create a mutex that prevents resource destruction and resource acquisition for a thread from happening at the same time.

If you insist on flagging resources for deletion while threads are working on them, use a refcount (and use atomic increment/decrement!) and decref the resource when it leaves the main resource pool so a work thread will nukes it when it finishes.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
If you're on Windows and the remote store has SCP or SFTP, then WinSCP has a "keep up to date" feature that keeps a local and remote folder in sync.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Princess Kakorin posted:

EDIT: And what's the deal with void pointers? I've read up on them, but don't quite grasp them.
Void pointers are for representing a pointer that could be to anything rather than data of any particular type. The stride of the contents is unknown so pointer arithmetic and indexes on them are illegal, the only thing you can do with them is cast them to a more useful type.

A nice example of where this is useful is memcpy, which takes a void pointer destination and a constant void pointer source, and the reason for that is that memcpy is a legal function to call on any type of data, whether it's a number, a structure, or array of values.


"new" is an allocation operation, it allocates a block of memory and returns a pointer to it, so the result of "new A" is actually a pointer of the type "A*"

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Is there a library out there that provides malloc/realloc/free facilities using an existing flat memory buffer? Preferably one that isn't GPL?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
If you'd prefer a web-based reference then this one's pretty good:
http://www.cplusplus.com/reference/clibrary/

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Has anyone been messing with Visual Studio 2012 Express RC?

I'm trying to find out if they removed the Memory and Thread windows. They documented them as unavailable in Visual C++ 2010, but you could still access them with Expert Settings enabled. The likelihood of that being a mistake combined with their supposed original plan to drop C++ support from Express entirely has me wondering if they'll still be there next round.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Aliasing rules are bothering me. Long story short, I need a version of memcpy that is guaranteed to copy aligned pointers atomically (on any platform I care about, that means loading and storing as a pointer-sized value), but the data can contain anything. I'm pretty sure the stock memcpy will do this in most scenarios, but I can't be 100% sure it won't optimize to rep stos or something like that.

At the same time, I'm trying to stay strict aliasing clean and it looks like that can only be accomplished if I was copying char-sized data, or was using a union, but a union will only guarantee aliasing of types contained in the union.

Is there a way to do this? Would declaring the destination volatile enforce that potentially-aliased values are reloaded after?

OneEightHundred fucked around with this message at 21:12 on Sep 7, 2012

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

floWenoL posted:

What's wrong with casting your pointers to char pointers, which can alias anything?
The problem is that if they're copied as chars, then the pointer-sized value copies may not be atomic, which is necessary in this case. I'm pretty sure recasting the pointers won't fix that since aliasing affects value load/stores, not pointer conversion.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

rjmccall posted:

Alternatively, if you put your memcpy in a file by itself, I promise you will not have optimization problems, even if that one function technically violates aliasing rules.
Does that still work even with whole program optimization?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Visual Studio, but there'll invariably be a GCC port at some point.

e: Apparently VS took out the aliasing optimizations in 2005 and replaced them with a function-level keyword. :psyduck:

OneEightHundred fucked around with this message at 22:42 on Sep 7, 2012

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

floWenoL posted:

You may have to use atomic instructions. If so, then you can just use char *.
Like I said, char is out because char will emit as multiple single-byte copies, due to the possibility of the memory regions overlapping. I'm pretty sure copying it as a larger value forces the compiler to emit instructions that will fully read the value before writing it out.

Also I don't need them to be atomic in the sense of surviving load/store reordering, I just need them to be atomic in the sense that partially-written memory addresses will never be visible to another thread. In practice, every platform I can imagine caring about will guarantee write atomicity of pointer-sized values to aligned addresses, which is all I want. I just want to be able to do it without the compiler deciding that values it reads from the destination area haven't changed.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

covener posted:

I have to confess to not following the topic, but memcpy does not tolerate overlapping arguments. Maybe that tainted some previous test?
The problem is that I'm not using memcpy, I need something that will guarantee a particular behavior: That pointer values contained in the source data (which can be mixed data, but the pointer values will be aligned) will not be visible in a partially-written state at the destination to other threads.

memcpy does this on Windows at least and glibc probably does it too, but it's not guaranteed and intrinsics may cause other behavior (like emitting rep stos).

Implementing it using chars, i.e.
code:
while(numBytes--) *destChar++ = *srcChar++;
...will not work because the compiler can't be sure that destChar and srcChar don't overlap, so it will emit the copies as single-byte read/writes to ensure the correct behavior if, for example, srcChar is only offset 2 bytes from destChar.

Copying it as an array of pointers will work, but the problem is that compilers are allowed to assume that, say, a float value read from the same destination region was not changed from the operation.

OneEightHundred fucked around with this message at 16:54 on Sep 8, 2012

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Doesn't C++ have a way to implement template methods only for certain template parameter matchups?

i.e. I'm trying to port a some old linear algebra types and make various aspects of it generic, but some things have implementations that are specific to particular row/column counts (i.e. fast inversions, cross product, etc.)

I'm trying this:
code:
template<class _Tfloat, LargeInt _Trows, LargeInt _Tcols>
class Mat
{
    ...
    Mat<_Tfloat, _Tcols, _Trows> Inverse() const;
    ...
};
... but it says that it can't match the definition when I try this:
code:
template<class _Tfloat>
inline Mat<_Tfloat, 3, 3> Mat<_Tfloat, 3, 3>::Inverse() const
{
   ...

OneEightHundred fucked around with this message at 02:28 on Mar 4, 2013

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

tractor fanatic posted:

No. You have to specialize the entire class. You might want to consider doing it with template functions instead, which you can specialize.

edit: or you can use CRTP to make some mixins.
I decided to work around it by using static functions that do basically the same thing and are called by the instance method, but the overloads only match if they're called using a type that supports them.

code:
template<class _Tfloat, LargeInt _Trows, LargeInt _Tcols>
class Mat
{
private:
    static Mat<_Tfloat, 3, 3> Inverse(const Mat<_Tfloat, 3, 3> &self);
public:
    inline Mat<_Tfloat, _Tcols, _Trows> Inverse() const
    {
        return Inverse(*this);
    }
};
:effort:

The language not supporting it in instance methods seems kind of weird.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
I'm not sure what you're passing in there, but make sure that you're not overflowing beyond the integer resolution. You mentioned 200000/200003, multiplying those gives you 40000600000, but anything over 134217727 is an overflow and the higher bits will be truncated.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Does calling a function allow strict aliasing violations, even if the function is inlined? i.e. if I write this:

code:
inline void copy4(void *dest, const void *src)
{
    *static_cast<int*>(dest) = *static_cast<const int *>(src);
}

int main(int argc, const char **argv)
{
    float f1 = 1.0f;
    float f2 = 0.0f;
    copy4(&f2, &f1);
    printf("Should be 1: %f\n", f2);
    return 0;
}

... is that always going to work?

OneEightHundred fucked around with this message at 00:09 on Aug 19, 2013

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Ciaphas posted:

I hate this/these loving language(s). :sigh:
It's actually a pretty good idea to get down what the guarantees of types are and make your conversions as explicit as possible. I've seen numerous codebases run into severe problems porting to 64-bit for example because they cast address differences (or raw pointers) to int. Newer high-level languages often require very explicit conversions between types that are of questionable compatibility or unspecified accuracy, i.e. C# uses TimeSpan rather than a numeric type and converting to and from chars requires using a text encoding.

OneEightHundred fucked around with this message at 15:31 on Sep 1, 2013

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Windows Forms is pretty much the thing to use for Windows-only UI right now. If you need native code with it then just write a mixed-mode app.

e: WPF is probably better for larger ongoing projects, WinForms is better for small stuff because WPF's setup time is annoying (gently caress XAML).

OneEightHundred fucked around with this message at 22:23 on Sep 2, 2013

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

GrumpyDoctor posted:

VS2010 is buggy as hell when you've got a C++/CLI project in your solution.
It's not that buggy, the main problem is that you have to manually set debugging to mixed mode or it'll vomit any time something goes wrong in the managed code. The Auto debug mode option basically doesn't work.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Another dumb aliasing question: How does it work with struct members, or is that also undefined?

i.e. if I do this:

code:
struct StructA
{
    int a;
    int b;
};

struct StructB
{
    int a;
    int b;
};

int main(int argc, const char **argv)
{
    StructA sa;
    sa.a = 1;
    sa.b = 2;

    printf("%i", reinterpret_cast<StructB*>(&sa)->a);
    return 0;
}
.... is that guaranteed to print 1, or does the fact that it's inside of incompatible structs make it undefined?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
The real-world application was an attempt to alias handle containers with compatible members. It sounds like it can't be done though, and if I'm one annoyance away from just going to -fno-strict-aliasing given that this is quickly becoming insufferable for low-level code and most of the advantages are easier to get by just aggressively pulling things into local vars than trying to guess when the optimizer will gently caress my code.

OneEightHundred fucked around with this message at 04:13 on Sep 22, 2013

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Vanadium posted:

Putting them all into a union doesn't work?
Only if I have a union with every instance of that container template in it (and that still won't work in compilers that disallow non-POD types in a union). The closest thing to a workaround is always do the loads/saves with a common type that's in all of the templates, which I can do (i.e. a void reference), but that also loses type information in the debugger and it requires a lot of shunting.

Worse still, I'm pretty sure using unions to alias is also non-standard behavior that some compilers will ignore (i.e. Sun CC), it just happens to be allowed by GCC despite other statically-provable aliasing (i.e. local vars) being ignored for some reason.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

fritz posted:

Do people still willingly use sun cc?
I haven't used it in years and years but I remember it being total poo poo.
I think Intel CC might ignore it to, and that's definitely used.

What they really need to do is just make may_alias standard (or make another memory model template for it like they did with std::atomic). char being the only guaranteed aliasable type is really stupid.

OneEightHundred fucked around with this message at 21:55 on Sep 22, 2013

Adbot
ADBOT LOVES YOU

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
Why even do that? Doing it for public members makes sense for C compatibility, but the rest is a weird half-way to member reordering.

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