Please create an account to participate in the Slashdot moderation system

 



Forgot your password?
typodupeerror
×

Comment Re:Good luck chasing that unicorn (Score 1) 144

Redmine is great. I use it for all our internal IT projects and also service desk. On desktop computer there is not really a need for native client as web based version works OK. For tablet and phones there are few native clients that use Redmine API and once I checkd them RedminePM worked very well for us.

Comment Re:C++ is hard (Score 1) 757

I think you are right that placement_new could be used to get a block of memory filled with the object without using malloc and without double-indirection when using it. It looks like every method on that static object has to be copied to the dummy object, so I'm not sure if that is a good selling point for C++.

What I was thinking of was some keyword added to the static that causes no change in any code except the destructor is not called. An idea I had was to use '&' without constructor args after it:

      static Foo&; // uses default constructor
      static Foo&(1,2,3); // uses some other constructor

However I am rather worried that this may collide with some existing syntax.

I never heard of a guarantee that statics are destroyed in the opposite order of creation. In fact this seems to be completely false in cases where a function containing a static variable is first run in a parallel thread. Wrapping statics in functions is useful to guarantee construction order, and I do it all the time, but never used it to control destruction order.

Even if destruction order could be controlled, it does not fix the real problem where the static object obtains a pointer to an object that was constructed later, generally for caching. An example is an OpenGL resource, you want your destructor to release the resource but that will crash if the OpenGL context has been destroyed. Adding an if statement to the destructor that is only true when your program is exiting is pretty distasteful.

Comment Re:Write-only code. (Score 1) 757

No, the lambda must not take the arguments by reference. This is because the original values can be destroyed before the lambda is run, invalidating the references.

do_something can take them by reference, the lambda calls it and the lambda is not destroyed until after it returns.

I think the job of figuring out which is more efficient should belong to the compiler, but this would require C++ to be redefined such that all arguments are possibly const references (ie a function cannot modify it's own arguments, or perhaps modification forces a copy inside the function).

Comment Re:Ahhhh, C++ (Score 1) 757

auto copy = string{mystring}.replace("from", "to"); and move semantics avoids the extra copy.

The string constructor does an unnecessary copy. You are correct that move semantics avoids yet another copy from the result to "copy". I have not found any way to do this except by having two different functions, one which does an in-place modification and another that returns a newly constructed string. This produces questions about how to name them, as only one of them gets the "good" name.

I have seen attempts to make a "modstring" subclass where the methods happen in-place. Not sure if this is a great idea.

I suspect disagreement about how to do this is why all these useful functions have not been added to strings.

In any case I also apologize, your style of in-place modification would not prevent reference-counting implementations. The problem is operator[] only. If in fact you changed characters with a string.replace_char(n,c) it could be done with reference counted strings.

Comment Re: Write-only code. (Score 2) 757

His code is constructing a lamda as a local value, not copying it anywhere, and directly calling it, then destroying it. When the call is done every detail of the lambda is known precisely, and this can be optimized (apparently g++ does so, too).

The original post constructs a lambda and passes it by value to the thread constructor and then exits before the lambda is used. This requires a and b to be copied. Later the forked thread executes the lambda. It is highly unlikely the locations of a and b in the lamda structure are in the memory location that the lambda function looks for them, so they must be copied (and memmove is explicitly not allowed by C++, you must use the copy or move constructor).

The fix is to make do_something take the arguments as const references, which are really pointers, and then the lambda caller can just make the pointers point at where a and b are in the lambda structure.

C++ would have been helped considerably if all arguments to functions were const references (with the compiler allowed to choose whether to copy or make a reference depending on which is more efficient). You could use volatile to make a non-const reference if needed (though most code I have seen use a pointer for out parameters). This apparently would break too much code, but is by far the biggest source of unexpected inefficiency in C++ and really should be fixed rather than having the code writers decide whether a copy or reference is faster.

Comment Re:Write-only code. (Score 5, Informative) 757

The sample code will copy a and b twice, once to put them in the lambda closure

Only without optimization flags enabled. Otherwise the lambda will be inlined in most cases.

BZZT! Wrong! Think: what happens if a and b are local variables and the function creating the thread returns before the lambda runs? They must be copied to somewhere that is not destroyed by the caller returning. That copy is not in the correct location because they are created before the thread stack, so another copy is unavoidable. The only way to fix it is to make do_something take const references. Though it is true that if do_something was inline it would probably fix it.

Show me the code

Yes it is ugly and I never claimed otherwise. The problem is that C++ compiles into the equivalent of this and it is hidden behind the scenes. Here is is pretty obvious that I must not pass a pointer to a or b, not so clear in C++:

#include <pthread.h>
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>

void do_something(int a, int b) {
    printf("do_something %d %d\n", a, b);
}

typedef struct {
    int a, b;
} lambda_args;

void* lambda_run (void *p) {
    lambda_args* v = (lambda_args*)p;
    do_something(v->a, v->b);
    free (v);
    return 0;
}

void thread_do_something (int a, int b)
{
    lambda_args* v = (lambda_args*)malloc(sizeof(lambda_args));
    v -> a = a;
    v -> b = b;
    pthread_t thread;
    pthread_create (&thread, 0, lambda_run, v);
}

int main()
{
    thread_do_something(1, 2);
    thread_do_something(3, 4);
    sleep (1);
    return 0;
}

Comment Re:C++ is hard (Score 1) 757

assumptions about the order of static variable destructors

Yes this is a huge problem. Almost all of our code has static objects defined something like this:

    static Foo& theStaticFoo = new Foo(2);

This is so the destructor is not run when the program exits, since it will usually crash because Foo relies on some other object that has already been destroyed.

An annoyance of this is that a non-optimizing compiler will do an extra level of indirection, and call malloc at startup.

It would be nice if C++ added some kind of syntax to make a static object that does not call the destructor without making construction or use less efficient. Possibly somehow sticking the much-overused "const" keyword in there somewhere?

Comment Re:Ahhhh, C++ (Score 1) 757

I don't know why you want to modify strings in-place. Seems like you are complaining that it is not C-like. It would be much better if values were returned, for instance your "mystring.replace("from","to")" would not change mystring, but instead return a new string with the replacement done.

One of the biggest mistakes in std::string is that operator[] returns a non-const reference. This is so all those people raised on Visual Basic could capitalize by doing a[0]=toupper(a[0]). It also means that efficient copying of strings by using reference counts is impossible.

Making it a template just because a bunch of loonines thought that you could not do Unicode unless you made all the characters the same size was another mistake. Not only is the code unreadable and impossible to optimize, those idiots ended up with UTF-16 which is variable sized anyway. Duh.

Comment Re:Write-only code. (Score 4, Informative) 757

The sample code will copy a and b twice, once to put them in the lambda closure, and then to pass them as arguments to do_something. Some may consider this wasteful (the easiest fix is to modify do_something to take the values as const references).

This is the general problem with C++, in that the shortest code is often the slowest. Adding const references to the declaration of do_something would remove the useless extra copy. The slowness is visible in C, where you would probably allocate a structure containing the copy of a and b, and have pthread_create call a function that copies them to the arguments to do_something and calls it, then deletes the temporary structure. This is equivalent to what the C++ compiles into but all the inefficiency is visible. This is the primary complaint about C++ verses C.

PS: I use C++ all the time and prefer it over C. But you do require a good knowledge of what it turns into, often stated in a pseudo-C, to figure out how and why things work and why slight variations (try using [&] instead of [=] in your lambda!) break in horrific ways.

Comment Re:Anybody remember framebuffer madness? (Score 1) 166

The acceleration is now accessible by the client program as it draws into it's own frame buffer. On modern systems the client program can use the GPU as a resource to compute it's own results.

Wayland mostly is providing a way of telling a central service how to combine the client's frame buffer with all the other clients into the image put on the screen.

Slashdot Top Deals

Anything free is worth what you pay for it.

Working...