Sunday, March 8, 2015

Digest for comp.lang.c++@googlegroups.com - 22 updates in 4 topics

JiiPee <no@notvalid.com>: Mar 08 12:25AM

On 07/03/2015 23:17, Richard Damon wrote:
> it can't be a template) with run time handling of using a version that
> isn't supported for this type of animal. This gives your run time
> binding.
 
This was my old way which I wanted to change because I did not want to
repeat all 5 functions 10 times for different types as they all were
very similar. So wanted to make one template class and create different
instances by changing the type.
 
 
> Two, is to have different versions of getAnimal for each type of
> animal, which returns the right type of pointer for that animal.
 
I ll have to check this..
 
Richard Damon <Richard@Damon-Family.org>: Mar 07 08:28PM -0500

On 3/7/15 7:25 PM, JiiPee wrote:
> repeat all 5 functions 10 times for different types as they all were
> very similar. So wanted to make one template class and create different
> instances by changing the type.
 
But you don't need 5x10 functions. You have a "dummy" copy of each
function in AnimalBase (to give the error for using the wrong type), and
you over ride in each animal the type that matches the type of animal,
so dog<int> only needs to define speak(int). You need that second
definition anyways to define what it is supposed to do, so the only
"extra" code is the dummy versions in AnimalBase. You also need to
decide what speak(int) should do in something based on Animal<string>.
>> have the cast in the template. This seems to be what you are looking for.
 
>> The issue is that you can't overload on return type or make the static
>> return type of a function determined at run time.
 
I will say that something seems a bit strange to have a collection of
objects with this type of differing APIs.
JiiPee <no@notvalid.com>: Mar 08 02:04AM

On 08/03/2015 01:28, Richard Damon wrote:
> function in AnimalBase (to give the error for using the wrong type),
> and you over ride in each animal the type that matches the type of
> animal, so dog<int> only needs to define speak(int).
 
aha. I though you meant not to use templates at all.
But this I am already doing: eatch type will get its own speak function
as a specilization function.
Richard Damon <Richard@Damon-Family.org>: Mar 07 09:56PM -0500

On 3/7/15 9:04 PM, JiiPee wrote:
 
> aha. I though you meant not to use templates at all.
> But this I am already doing: eatch type will get its own speak function
> as a specilization function.
 
But if the speak functions are put into AnimalBase, as virtual
functions, then you only need a pointer to AnimalBase to get access to
them, and being virtual, you will get the more derived version if defined.
 
The one problem is that speak can't be a template function as template
member functions can't be virtual (it causes practicality problems with
building the vtable for the class) so you need to list the functions
individually
 
class AnimalBase {
 
public:
virtual void speak(int);
virtual void speak(std::string);
...
};
 
Note that in your derived Animal class, speak is NOT a template member
function, just an ordinary member function in a template class using the
template parameter, so this is ok. The one limitation is that AnimalBase
needs to know all the types that Animal will be instanced with.
 
This is what gives you run time binding.
JiiPee <no@notvalid.com>: Mar 08 03:23AM

On 08/03/2015 02:56, Richard Damon wrote:
 
> Note that in your derived Animal class, speak is NOT a template member
> function, just an ordinary member function in a template class using
> the template parameter, so this is ok.
 
This solves one problem possibly. But.... I actually forgot to mention
another even more importan issue (and thats why I was talking about
getting the pointer to Dog type so much): namely the most important
thing is to get the value of the object and be able to use it, namely
m_whatToSpeak.
Because its in Dog-class I really need a pointer to a dog class I think.
Yes, I can cast the AnimalBase to Dog, but this is why I was asking is
it possible to get Dog pointer so I do not need to cast. But seems like
its not easily possible to achieve. I would like to call like this:
 
int a = farm.getAnimal(0)->m_whatToSpeak;
std::string b = farm.getAnimal(1)->m_whatToSpeak;
 
(or instead of fm_whatToSpeak via a function call).
 
I tried the visitor method somebody mentioned, but I think there is the
same proglem that AnimalBase does not know the type of m_whatToSpeak so
it cannot have a virtual function to return m_whatToSpeak as a return
value (the visitor can use it but not return it). But I ll think about
if I need it as a return value or not...maybe getting the value by
reference parameter.
Richard Damon <Richard@Damon-Family.org>: Mar 07 10:41PM -0500

On 3/7/15 10:23 PM, JiiPee wrote:
> value (the visitor can use it but not return it). But I ll think about
> if I need it as a return value or not...maybe getting the value by
> reference parameter.
 
The answer to that is to use a setter function instead of directly
accessing the value to set. As to getting the values, do any non-member
function need to know this sort of detail? Remember that inside the
speak function, your this pointer is of the type of the object the
member function is a member of, not the base, so has full access to the
types.
 
Now, if you really are doing all of this work that is dependent on the
type of animal, you probably want the type specified get to return the
right type.
"Öö Tiib" <ootiib@hot.ee>: Mar 08 03:33AM -0700

On Sunday, 8 March 2015 05:23:35 UTC+2, JiiPee wrote:
> value (the visitor can use it but not return it). But I ll think about
> if I need it as a return value or not...maybe getting the value by
> reference parameter.
 
The derived classes are allowed to return values of covariant return
types from virtual functions in C++:
 
// a class, and a subclass
class Foo {};
class Bar : public Foo {};
 
// covariant returning base class
class Baz
{
public:
virtual Foo* create() { return new Foo(); }
};
 
class Quux
: public Baz
{
public:
// Different return type, but it's allowed by the standard since Bar
// is derived from Foo
virtual Bar* create() { return new Bar(); }
};
 
int main()
{
Quux* tmp = new Quux();
Bar* bar = tmp->create();
}
 
That is not your problem. Your problem is that you want the caller to
get knowledge of the full type through base class pointer and for that
you need either double dispatch (visitor pattern) or RTTI
('dynamic_cast'/'typeid').
 
Most cases when you need to use RTTI manually are indicating
that the design of hierarchy is weak. It may be still used when
redesign of hierarchy is estimated too expensive or not allowed.
It can't be the case with your own classes.
 
The visitor pattern is more powerful since same visitor can visit
types of unrelated hierarchies. The technique is like adding narrow
virtual interface from outside. It is complex technique and so I
have seen people misunderstanding and misusing it and screwing all
up.
JiiPee <no@notvalid.com>: Mar 08 12:55PM

On 08/03/2015 10:33, Öö Tiib wrote:
> get knowledge of the full type through base class pointer and for that
> you need either double dispatch (visitor pattern) or RTTI
> ('dynamic_cast'/'typeid').
 
but how would you implement the visitor (the idea)? I tried:
 
class AnimalBase
{
..
virtual void accept(Farm* farm) = 0;
}
;;;;
template <typename T>
void Dog<T>::accept(Farm* farm)
{
farm->visit(this);
}
 
then :
farm.getAnimal(0)->accept(&farm);
 
But how does this help to return the Dog? I dont understand how will
that return Dog. Is this what you meant? Where would the dog be returned?
 
 
 
 
JiiPee <no@notvalid.com>: Mar 08 01:12PM

On 08/03/2015 12:55, JiiPee wrote:
> farm.getAnimal(0)->accept(&farm);
 
> But how does this help to return the Dog? I dont understand how will
> that return Dog. Is this what you meant? Where would the dog be returned?
 
or is it more like sending some kind of data object as a visitor and
this object then captures the m_whatToSpeak value?
 
like:
struct Values
{
int* intValue;
string* stringValue;
};
 
then :
Values data;
farm.getAnimal(0)->accept(&data);
 
and this data capture the value to intValue or stringValue depending
what type it is?
JiiPee <no@notvalid.com>: Mar 08 01:14PM

On 08/03/2015 13:12, JiiPee wrote:
> farm.getAnimal(0)->accept(&data);
 
> and this data capture the value to intValue or stringValue depending
> what type it is?
 
I would be quite happy for this approach if it works and is the
recommended way.
Paavo Helde <myfirstname@osa.pri.ee>: Mar 08 08:16AM -0500


> But how does this help to return the Dog? I dont understand how will
> that return Dog. Is this what you meant? Where would the dog be
> returned?
 
If you want derived class (Dog) returned at compile time you must be used
a compile-time feature, i.e. a template. In other words, the function
returning Dog must be a template, and it must be instantiated with the
Dog type, again at compile-time.
 
For example, the Dog class itself knows it is Dog, at compile time, so if
it there is a virtual function of Dog which is calling some template
function, it can easily instantiate it as Dog. I guess this might be what
Öö Tiib meant by using the visitor pattern.
 
hth
Paavo
JiiPee <no@notvalid.com>: Mar 08 01:23PM

On 08/03/2015 13:16, Paavo Helde wrote:
> a compile-time feature, i.e. a template. In other words, the function
> returning Dog must be a template, and it must be instantiated with the
> Dog type, again at compile-time.
 
I see. So something like:
if(farm.animal[0].type == DOG)
Dog* dog = farm.getAnimal<Dog>[0];
 
so must ask it via template argument.
 
JiiPee <no@notvalid.com>: Mar 08 01:47PM

On 08/03/2015 13:16, Paavo Helde wrote:
> Öö Tiib meant by using the visitor pattern.
 
> hth
> Paavo
 
Well, this one works... just tested:
struct AnimalValues
{
int* intVal;
std::string* strVal;
 
void visit(Dog<int>* dog) { intVal = &dog->m_whatToSpeak; }
void visit(Dog<std::string>* dog) { strVal = &dog->m_whatToSpeak; }
};
...
main:
AnimalValues vals;
farm.getAnimal(0)->accept(&vals);
// now *vals.intVal contains the integer value (5)
farm.getAnimal(1)->accept(&vals);
// now *vals.strVal contains the string value (Willy)
 
 
Well, I am pretty happy for this solution :). Thanks guys (the
suggestion about Visitor helped here)....I think I might go for this
solution (if it just works also with my real project which is a bit more
complex... but it should) this time, its close to my old solution also
so just an improvement.
 
This seems to work best with my real project as well currently.
JiiPee <no@notvalid.com>: Mar 08 01:48PM

On 08/03/2015 10:33, Öö Tiib wrote:
> types of unrelated hierarchies. The technique is like adding narrow
> virtual interface from outside. It is complex technique and so I have
> seen people misunderstanding and misusing it and screwing all up.
 
Thanks, I think I chose this Visitor thing. in the other post I describe
how it work with my code quite well...
JiiPee <no@notvalid.com>: Mar 08 01:52PM

On 07/03/2015 20:39, Mr Flibble wrote:
 
> Have a look at the visitor pattern.
 
> /Flibble
 
ye you were right this time :). After long thinking I chose to use it.
How did you know?
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Mar 08 06:23PM

On 08/03/2015 13:52, JiiPee wrote:
 
>> /Flibble
 
> ye you were right this time :). After long thinking I chose to use it.
> How did you know?
 
I am right every time mate; and all knowing. I am God to you.
 
Sausages.
 
/Flibble
JiiPee <no@notvalid.com>: Mar 08 08:39PM

On 08/03/2015 18:23, Mr Flibble wrote:
 
> I am right every time mate; and all knowing. I am God to you.
 
> Sausages.
 
> /Flibble
 
I think you just guessed... and were lucky.. heh
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Mar 08 08:40PM

On 08/03/2015 20:39, JiiPee wrote:
 
>> Sausages.
 
>> /Flibble
 
> I think you just guessed... and were lucky.. heh
 
In your dreams mate.
 
/Flibble
JiiPee <no@notvalid.com>: Mar 08 08:54PM

On 08/03/2015 20:40, Mr Flibble wrote:
 
>> I think you just guessed... and were lucky.. heh
 
> In your dreams mate.
 
> /Flibble
 
be honest.. :) God is watching...
David Brown <david.brown@hesbynett.no>: Mar 08 08:57PM +0100

On 07/03/15 20:44, Jorgen Grahn wrote:
> documentation format, but that's where the full compiler documentation
> is, so you need to have it and be able to navigate it.
 
> /Jorgen
 
I have never found "info" pages to be any use. The gcc manuals are fine:
 
<https://gcc.gnu.org/onlinedocs/>
 
Use the online html, html tarballs, or pdf files according to preference.
 
gcc also comes with a fairly good built in help (with "--help -v" as a
starting point) - recent versions let you get details of different
groups of command-line switches.
Ramine <ramine@1.1>: Mar 07 10:04PM -0800

Hello...
 
 
We have to be smart when thinking about reader-writer consistent
mechanism which has different kinds of characteristics... first comes
first, we have to know an important thing is how to evaluate those
reader=writer mechanisms ? i think we have to evaluate them
using the following criteria: scalability, starvation-freedom and power
efficiency..
 
So i will start with the following reader-writer lock, look at it
in the following webpage:
 
http://concurrencyfreaks.blogspot.ca/search?updated-min=2015-01-01T00:00:00%2B01:00&updated-max=2016-01-01T00:00:00%2B01:00&max-results=7
 
this algorithm is using the same algorithm as the following algorithm by
Joe Duffy an architect at Microsoft:
 
http://joeduffyblog.com/2009/02/20/a-more-scalable-readerwriter-lock-and-a-bit-less-harsh-consideration-of-the-idea/
 
If we judge those reader-writer locks on the criteron of
starvation-freedom, those reader-writer locks above are not
starvation-free, but my scalable RWLock called LW_RWLockX and my
scalable RWLock called RWLockX are starvation-free.
 
You can download my scalable RWLocks that are starvation-free from:
 
https://sites.google.com/site/aminer68/scalable-rwlock
 
 
Now if we judge those reader-writer locks above on the power efficiency
criterion , those reader-writer above are less efficient than
my scalable RWLock called LW_RWLockX and less efficient than my
scalable RWLock called RWLockX.
 
So now we will evaluate those reader-writer locks above on the criterion
of scalability on multicores:
 
I must say that they are both innefficient when it comes to scalability
on multicores and i will explain to you why:
 
I must say that we have to be carefull, because i have just
read the above webpages about those more scalable reader/writer lock
by an architect at microsoft called Joe Duffy and a PhD called Pedro
Ramalhete... but you have to be carefull because those reader/writer
locks are not really scalable, and i will think as an architect and
explain to you why...
 
Here is the webpage, and my explanation follows...
 
http://joeduffyblog.com/2009/02/20/a-more-scalable-readerwriter-lock-and-a-bit-less-harsh-consideration-of-the-idea/
 
http://concurrencyfreaks.blogspot.ca/search?updated-min=2015-01-01T00:00:00%2B01:00&updated-max=2016-01-01T00:00:00%2B01:00&max-results=7
 
 
So look inside the EnterWriteLock() of the reader/writer above of Joe
Duffy, you will notice that it is first executing
Interlocked.Exchange(ref m_writer, 1), that means it is atomicaly making
m_writer equal 1, so that to block readers from entering the reader
section, but this is garbage, cause look after that he is doing this:
 
for (int i = 0; i < m_readers.Length; i++)
 
while (m_readers[i].m_taken != 0) sw.SpinOnce();
 
So after making m_writers equal 1 so that to block the readers,
he is transfering many cache-lines between cores, and this is really
expensive and it will make the serial part of the Amdahl's law bigger
and bigger when more and more cores will be used , so this will not
scale, so it is kind of garbage.
 
My explanation applies to the other algorithm of Pedro Ramalhete because
the Joe Duffy reader-writer lock above is the same algorithm.
 
But the Dmitry Vyukov distributed reader-writer mutex doesn't have this
weakness, because look at the source code here:
 
http://www.1024cores.net/home/lock-free-algorithms/reader-writer-problem/distributed-reader-writer-mutex
 
Because he is doing this on the distr_rw_mutex_wrlock() side:
 
for (i = 0; i != mtx->proc_count; i += 1)
pthread_rwlock_wrlock(&mtx->cell[i].mtx);
 
 
So we have to be smart here and notice with me that as the "i" counter
variable goes from 0 to proc_count, the reader side will still be
allowed to enter and to enter again the reader section on scenarios with
more contention, so in contrast with the above reader-writer lock, this
part of the distributed lock is not counted as only a serial part of the
Amdahl's law, because it allows also the reader threads to enter
and to enter again the reader section, so this part contains a parallel
part of the Amdahl's law, and this makes this distributed reader-writer
lock to effectively scale. This is even better with my Distributed
sequential lock , because my Distributed sequential lock scales even
better than the distributed reader-writer mutex of Dmitry Vyukov.
 
But there is a weakness on the distributed reader-writer mutex of Dmitry
Vyukov, because the writer's side will become slower and slower when you
will add more and more cores and use more and more threads , because it
will transfers too many cache-lines and this is really expensive and
this will make the writer's side too slow and this is a real problem,
because this reader-writer mutex does effectively scale the readers but
the writer's side will become slower and slower
when there is more cores and more threads.
 
 
 
Now let us talk about my scalable SeqlockX algorithm that you will
find here:
 
https://sites.google.com/site/aminer68/scalable-seqlockx
 
 
This scalable SeqlockX is scalable reader-writer mechanism that
is really scalable on multicores and it improve on the classical Seqlock
because it eliminates completly the "livelock" of the readers when there
is many writers. I think my new scalable SeqlockX algorithm is the right
tool to use if you want to replace scalable RWLocks or to replace Dmitry
Vyukov's distributed reader-writer mutex, it can even replace RCU, it
has good characteristics: since it doesns't "livelock" the readers when
there is many writers, and since it is extremely fast
and since it is really "scalable" and more scalable and faster on more
cores than Dmitry Vyukov's distributed reader-writer mutex, so i think
you have to port it to C++ and Java and C# also.
 
As you have noticed, currently , I have implemented my algorithm for
Delphi and FreePascal compilers...
 
You can download my scalable SeqlockX and read about the algorithm from:
 
https://sites.google.com/site/aminer68/scalable-seqlockx
 
 
 
 
Thank you,
Amine Moulay Ramdane.
bleachbot <bleachbot@httrack.com>: Mar 08 04:04AM +0100

You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: