Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

simulating threads

2 views
Skip to first unread message

prashanth

unread,
Jun 26, 2002, 12:01:55 AM6/26/02
to
i was asked to write a thread program in C . the best one is a
producer - consumer program , where the producer increments a number
(say i++) and the consumer consumes the same.i just need a starter,
not the whole code. help will be greatly appreciated.
thanx

Andreas Kähäri

unread,
Jun 26, 2002, 12:29:06 AM6/26/02
to
Submitted by "prashanth" to comp.lang.c:

C doesn't support threads. You will need to use the
C interface to some thread library for your platform.
Ask in comp.programming.threads. Their FAQ is at
http://www.serpentine.com/~bos/threads-faq/


--
Andreas Kähäri
--------------------------------------------------------------
Stable, secure, clean, free: www.netbsd.org

Richard Heathfield

unread,
Jun 26, 2002, 6:02:19 AM6/26/02
to

Oddly, I just posted a program last night (in comp.programming) which
does something remarkably similar. I don't suggest that you hand it in
as homework, as it was not intended as a thread simulator example.
Nevertheless, you might find it useful for ideas.

Co-operative thread-faking isn't all that difficult in C. One way you
could do it is to set up a circular list of callbacks and a message
queue. Kind of "Windows for people who don't like Windows". :-)

--
Richard Heathfield : bin...@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

CBFalconer

unread,
Jun 26, 2002, 5:45:32 PM6/26/02
to
Richard Heathfield wrote:
>
> prashanth wrote:
> >
> > i was asked to write a thread program in C . the best one is a
> > producer - consumer program , where the producer increments a number
> > (say i++) and the consumer consumes the same.i just need a starter,
> > not the whole code. help will be greatly appreciated.
>
> Oddly, I just posted a program last night (in comp.programming) which
> does something remarkably similar. I don't suggest that you hand it in
> as homework, as it was not intended as a thread simulator example.
> Nevertheless, you might find it useful for ideas.
>
> Co-operative thread-faking isn't all that difficult in C. One way you
> could do it is to set up a circular list of callbacks and a message
> queue. Kind of "Windows for people who don't like Windows". :-)

Can you say "non-preemptive multitasking"? Or Win <= 3.1?

BTW I started to refer the OP to your c.p posting, but thought
better of it since you do live here. From my headers/download
ratio, sometimes as high as 10, in that group I assume the Nilges
war rages on.

--
Chuck F (cbfal...@yahoo.com) (cbfal...@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


Lew Pitcher

unread,
Jun 26, 2002, 3:34:20 PM6/26/02
to
Andreas Kähäri wrote:
>
> Submitted by "prashanth" to comp.lang.c:
> > i was asked to write a thread program in C . the best one is a
> > producer - consumer program , where the producer increments a number
> > (say i++) and the consumer consumes the same.i just need a starter,
> > not the whole code. help will be greatly appreciated.
> > thanx
>
> C doesn't support threads.

True and not true. There's no problem writing valid ISO C 99 code that
implements threading. I've done so, and demonstrated it here.

> You will need to use the
> C interface to some thread library for your platform.

Not necessarily so, but it _is_ a much better idea to use a pre-built
thread library instead of rolling your own threading core.

> Ask in comp.programming.threads. Their FAQ is at
> http://www.serpentine.com/~bos/threads-faq/

Very good advise.

--
Lew Pitcher

Master Codewright and JOAT-in-training

Richard Heathfield

unread,
Jun 29, 2002, 3:35:12 PM6/29/02
to
CBFalconer wrote:
>
> Richard Heathfield wrote:
> >
> > prashanth wrote:
> > >
> > > i was asked to write a thread program in C . the best one is a
> > > producer - consumer program , where the producer increments a number
> > > (say i++) and the consumer consumes the same.i just need a starter,
> > > not the whole code. help will be greatly appreciated.
> >
> > Oddly, I just posted a program last night (in comp.programming) which
> > does something remarkably similar. I don't suggest that you hand it in
> > as homework, as it was not intended as a thread simulator example.
> > Nevertheless, you might find it useful for ideas.
> >
> > Co-operative thread-faking isn't all that difficult in C. One way you
> > could do it is to set up a circular list of callbacks and a message
> > queue. Kind of "Windows for people who don't like Windows". :-)
>
> Can you say "non-preemptive multitasking"? Or Win <= 3.1?

Yes. :-)

>
> BTW I started to refer the OP to your c.p posting, but thought
> better of it since you do live here. From my headers/download
> ratio, sometimes as high as 10, in that group I assume the Nilges
> war rages on.


It has, at least, turned to programming matters now. Nilges has claimed
that to program a new application in C would be incompetent and
unethical; he says malloc is dangerous and should not be used; and he
has produced C code to prove that he, at least, should not be let loose
with a C compiler. If you want to know more, tune in yourself. :-)

Greg Martin

unread,
Jun 29, 2002, 4:01:53 PM6/29/02
to
On Sat, 29 Jun 2002 20:35:12 +0100, Richard Heathfield
<bin...@eton.powernet.co.uk> wrote:


>> BTW I started to refer the OP to your c.p posting, but thought
>> better of it since you do live here. From my headers/download
>> ratio, sometimes as high as 10, in that group I assume the Nilges
>> war rages on.
>
>
>It has, at least, turned to programming matters now. Nilges has claimed
>that to program a new application in C would be incompetent and
>unethical; he says malloc is dangerous and should not be used; and he
>has produced C code to prove that he, at least, should not be let loose
>with a C compiler. If you want to know more, tune in yourself. :-)
>

I have been setting my goals too high! Here I am trying to write good
programs when if I would only set out to prove I shouldn't be allowed
to I would almost certainly be guaranteeded of success.

CBFalconer

unread,
Jun 29, 2002, 6:14:14 PM6/29/02
to
Richard Heathfield wrote:
>
... snip ...

>
> It has, at least, turned to programming matters now. Nilges has claimed
> that to program a new application in C would be incompetent and
> unethical; he says malloc is dangerous and should not be used; and he
> has produced C code to prove that he, at least, should not be let loose
> with a C compiler. If you want to know more, tune in yourself. :-)

Are you recommending a British style driving test for operating a
C-compiler in public? Like the woman who took thirty years to
pass, and hit the news here a while ago when she made it.

Exercise for him - build a singly linked list of arbitrary length
without malloc. Having done it with recursive calls, now reverse
the list. Then sort it. Delete the median item.

Brendan Sechter

unread,
Jun 29, 2002, 7:31:11 PM6/29/02
to
In article <3D1E236D...@yahoo.com>, CBFalconer wrote:
[SNIP]

> Exercise for him - build a singly linked list of arbitrary length
> without malloc. Having done it with recursive calls, now reverse
> the list. Then sort it. Delete the median item.

Although I do not doubt that it is possible, somehow that notion
frightens me...

-Brendan

Dave Vandervies

unread,
Jun 30, 2002, 3:59:43 AM6/30/02
to
In article <3D1E236D...@yahoo.com>,

CBFalconer <cbfal...@worldnet.att.net> wrote:
>Richard Heathfield wrote:
>>
>... snip ...
>>
>> It has, at least, turned to programming matters now. Nilges has claimed
>> that to program a new application in C would be incompetent and
>> unethical; he says malloc is dangerous and should not be used; and he
>> has produced C code to prove that he, at least, should not be let loose
>> with a C compiler. If you want to know more, tune in yourself. :-)

>Exercise for him - build a singly linked list of arbitrary length


>without malloc. Having done it with recursive calls, now reverse
>the list. Then sort it. Delete the median item.

I seem to be very bored this weekend. (Last night I was up late reading
the Ontario Highway Traffic Act.)

The usual disclaimers apply: I wrote this in not much more time than
it took to type it out, and it's only been tested on the data you see
in main().
--------
struct link
{
int data;
struct link *next;
};

/*Note that all the links in the list created here go away when end_func
returns, so end_func should avoid storing pointers to them anywhere
that will stay around after it returns.
*/
void build_and_use_list(int *the_data,unsigned int nelems,struct link *tail,void (*end_func)(struct link *))
{
if(nelems)
{
struct link this_link;

this_link.data=*the_data;
this_link.next=tail;
build_and_use_list(the_data+1,nelems-1,&this_link,end_func);
return;
}
else
{
/*We've built the list, so do something useful with it*/
end_func(tail);
return;
}
}

#ifdef UNIT_TEST

#include <stdio.h>

void end_func(struct link *head)
{
struct link *curr;

/*Print the list we've built*/
puts("The initial list");
for(curr=head;curr;curr=curr->next)
printf("%d ",curr->data);
puts("");

/*Reverse it*/
{
struct link *last;

curr=head;
last=0;
while(curr)
{
struct link *temp=curr->next;
curr->next=last;
last=curr;
curr=temp;
}
head=last;
}

/*Print the reversed list*/
puts("The reversed list");
for(curr=head;curr;curr=curr->next)
printf("%d ",curr->data);
puts("");

/*Sort it*/
{
/*Simple insertion sort*/
struct link *prev;
struct link *sorted=0;

/*Handle first link as a special case*/
if(head)
{
sorted=head;
head=head->next;
sorted->next=0;
}

while(head)
{
struct link *temp=head->next;
curr=sorted;
prev=0;
while(curr && curr->data < head->data)
{
prev=curr;
curr=curr->next;
}

if(!prev)
{
/*If prev is null, the new link goes at the
head of the sorted list
*/
head->next=sorted;
sorted=head;
}
else
{
/*If prev is non-null, insert the new link
between prev and curr
*/
head->next=curr;
prev->next=head;
}
head=temp;
}
head=sorted;
}

/*Print the sorted list*/
puts("The sorted list");
for(curr=head;curr;curr=curr->next)
printf("%d ",curr->data);
puts("");

/*Delete the median item*/
{
/*Only works properly if:
-There are an odd number of items
-The median is unique
Does something sane but incorrect otherwise.
*/
struct link *fast,*slow,*before_slow;

fast=slow=head;
before_slow=0;
while(fast)
{
fast=fast->next;
if(fast)
{
before_slow=slow;
slow=slow->next;
fast=fast->next;
}
}

if(slow)
{
if(before_slow)
before_slow->next=slow->next;
else
/*slow==head*/
head=slow->next;
}

/*Note that when we leave this scope we've lost our last
reference to the deleted link
*/
}

/*Print the list with the median deleted*/
puts("The list with the median item deleted");
for(curr=head;curr;curr=curr->next)
printf("%d ",curr->data);
puts("");

}

int main(void)
{
int the_data[]={42,17,69,105,32};

build_and_use_list(the_data,(sizeof the_data / sizeof *the_data),0,end_func);

return 0;
}

/*
dj3vande@mef08:~/clc (0) $ gcc -W -Wall -ansi -pedantic -O -DUNIT_TEST list-no-malloc.c
dj3vande@mef08:~/clc (0) $ ./a.out
The initial list
32 105 69 17 42
The reversed list
42 17 69 105 32
The sorted list
17 32 42 69 105
The list with the median item deleted
17 32 69 105
*/

#endif
--------

Do I pass?


If we had objects with unlimited extent like in Scheme, using recursion
like this would actually be a quite reasonable way to build a list:
--------
;;;The usual disclaimers apply: Not run or tested, for illustration purposes
;;; only.
(define vector->reversed-list
(lambda (the-vector)
(letrec ((build-and-use-list
(lambda (numleft index tail end-func)
(cond ((> numleft 0)
(build-and-use-list (- numleft 1)
(+ index 1)
(cons
(vector-ref the-vector
index)
tail)
end-func))
(#t
(end-func tail))))))
(call/cc
(lambda (cont)
(build-and-use-list (vector-length the-vector)
1
'()
cont))))))
--------
(Here the value passed as end-func is a special function-like object
that, when passed a value, returns that value from the call/cc call
that created it. This is easier than passing the final value all the
way back up the call stack normally.)


dave

--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca
The allocated memory comes from a magical wardrobe in the midst of an enchanted
forest patrolled by fire-breathing dragons with a taste for human flesh. Only
malloc() and its fellow wizards know how to pacify the dragons. --Eric Sosman

CBFalconer

unread,
Jun 30, 2002, 8:16:33 AM6/30/02
to
Dave Vandervies wrote:
>
> In article <3D1E236D...@yahoo.com>,
> CBFalconer <cbfal...@worldnet.att.net> wrote:
> >Richard Heathfield wrote:
> >>
> >... snip ...
> >>
> >> It has, at least, turned to programming matters now. Nilges has claimed
> >> that to program a new application in C would be incompetent and
> >> unethical; he says malloc is dangerous and should not be used; and he
> >> has produced C code to prove that he, at least, should not be let loose
> >> with a C compiler. If you want to know more, tune in yourself. :-)
>
> >Exercise for him - build a singly linked list of arbitrary length
> >without malloc. Having done it with recursive calls, now reverse
> >the list. Then sort it. Delete the median item.
>
> I seem to be very bored this weekend. (Last night I was up late reading
> the Ontario Highway Traffic Act.)
>
> The usual disclaimers apply: I wrote this in not much more time than
> it took to type it out, and it's only been tested on the data you see
> in main().

... snip ...

Very good. I didn't claim any impossibility though. Actually the
building is the hardest part. It does have the advantage of never
waiting around for malloc/free :-) To make it harder I should
have added an insertion somewhere. The limits are going to be
much smaller than with malloc as many implementations limit stack.

Do I conclude that the OPP discovered you doing something
unmentionable and you are looking for an escape hatch? :-) Since
you did this I assume you found it.

Tor Rustad

unread,
Jun 30, 2002, 12:25:52 PM6/30/02
to
"Andreas Kähäri" <a...@freeshell.org.REMOVE> wrote in message

> Submitted by "prashanth" to comp.lang.c:
> > i was asked to write a thread program in C . the best one is a
> > producer - consumer program , where the producer increments a number
> > (say i++) and the consumer consumes the same.i just need a starter,
> > not the whole code. help will be greatly appreciated.
> > thanx

Bil Lewis (one of the regulars in comp.programming.threads), has a very
readable book (370 pages) in .pdf format, "Pthreads primer - a Guide to
Multithreading Programming", available free for download. It explains
different producer and consumer models in detail.

> C doesn't support threads.

Someone once said, "threads are for those who cannot write a FSM". :-)
So, since OP indicate that he want to simulate threads, that might be
exactly what he want to do...setjmp/longjmp comes to mind.

> You will need to use the C interface to some thread library for
> your platform.

Pthreads is avaiable on many platforms, UNIX, Linux, Win32...

> Ask in comp.programming.threads. Their FAQ is at
> http://www.serpentine.com/~bos/threads-faq/

c.p.t is a high quality news group, OP should read the FAQ
first, as so many fail to do here.

--
Tor <torust AT online DOT no>


Dave Vandervies

unread,
Jun 30, 2002, 1:52:38 PM6/30/02
to
In article <3D1EF075...@yahoo.com>,

CBFalconer <cbfal...@worldnet.att.net> wrote:
>Dave Vandervies wrote:
>>
>> In article <3D1E236D...@yahoo.com>,
>> CBFalconer <cbfal...@worldnet.att.net> wrote:
>> >Richard Heathfield wrote:
>> >>
>> >... snip ...
>> >>
>> >> It has, at least, turned to programming matters now. Nilges has claimed
>> >> that to program a new application in C would be incompetent and
>> >> unethical; he says malloc is dangerous and should not be used; and he
>> >> has produced C code to prove that he, at least, should not be let loose
>> >> with a C compiler. If you want to know more, tune in yourself. :-)
>>
>> >Exercise for him - build a singly linked list of arbitrary length
>> >without malloc. Having done it with recursive calls, now reverse
>> >the list. Then sort it. Delete the median item.
>>
>> I seem to be very bored this weekend. (Last night I was up late reading
>> the Ontario Highway Traffic Act.)
>>
>> The usual disclaimers apply: I wrote this in not much more time than
>> it took to type it out, and it's only been tested on the data you see
>> in main().
>
>... snip ...
>
>Very good. I didn't claim any impossibility though. Actually the
>building is the hardest part. It does have the advantage of never
>waiting around for malloc/free :-)

Building a non-mallocd linked list recursively isn't any harder than
mallocing space for it in a loop, at least if you're building it all at
once, but:

> To make it harder I should
>have added an insertion somewhere.

Ouch. I don't see any easy way of doing this without something not
entirely unlike call/cc that keeps the objects created in the function
called around after the continuation is invoked (either with persistent
objects or by creating a not-quite-a-continuation that duplicates the
current stack frame instead of returning to it):
--------
;;See, it's easy this way (and not much harder to create more than
;; one new link (the number to be determined any time before we get here)
;; instead of just one as shown here)

;We can't call cons because that's equivalent to mallocing a new link...
(let ((newhead call/cc (lambda (cont)
;...but we can create a cons cell this way,
; since that's the moral equivalent of an
; automatic variable.
(let ((newlink '(dummy-data)))
(set-cdr! newlink head)
(cont newlink)))))
(set! head newhead))
;;Now our list has a new node (with the data 'dummy-data) at the head,
;; and we can put it wherever we want it
--------
C could probably be coerced to do such a thing if you kick it hard enough
(probably by splitting up the do-the-work function into two (or n)
different functions, each of which ends with
--------
create_links_for_insertion(num_needed,next_part_func);
--------
), but it would be Ugly. Loops across something that needs to do an
insertion would be Very Ugly. (It'd need to be done by mangling (but
possibly only partially) the iteration into recursion, with the recursive
call going where you want to allocate space.)

(ObTopic: New C code challenge - find the least Ugly way to do this.)


> The limits are going to be
>much smaller than with malloc as many implementations limit stack.

This is why languages that allocate everything, including their equivalent
of stack frames, on the heap are useful when doing things recursively.
(Proper handling of tail calls is also nice (It's possible (and actually
a quite mechanical process given a working program of any sort) to write
a Scheme program that never returns from a function but is done strictly
with tail calls), but wouldn't be as helpful as it could be here because
we're actually creating new objects that need to stick around on every
call and not just return addresses and local variables whose usefulness
is over when we make the tail call.)


>Do I conclude that the OPP discovered you doing something
>unmentionable and you are looking for an escape hatch? :-)

No, though that seems to be everybody's guess. I just bought a bicycle,
and I was just checking to make sure that the things people in cars keep
yelling at me for are not only legal but also good form. (Most of them
are, and the rest have since changed.) Now all I need to do is find an
opportunity to ask one of those people in cars who keep yelling at me
whether they're familiar with it...

> Since
>you did this I assume you found it.

Hmm? Most penalties for offenses under the HTA are only fines, not
jail time. Unless you meant that now I have something other to do than


looking for an escape hatch?


dave

--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca
> What should such a standard mandate for systems which don't use
> directories, such as OS390? --Richard Heathfield and
A well-engineered fake. Chris Dollin in comp.lang.c

CBFalconer

unread,
Jun 30, 2002, 3:42:38 PM6/30/02
to
Dave Vandervies wrote:
> CBFalconer <cbfal...@worldnet.att.net> wrote:
> >>
... snip ...

>
> >Do I conclude that the OPP discovered you doing something
> >unmentionable and you are looking for an escape hatch? :-)
>
> No, though that seems to be everybody's guess. I just bought a bicycle,
> and I was just checking to make sure that the things people in cars keep
> yelling at me for are not only legal but also good form. (Most of them
> are, and the rest have since changed.) Now all I need to do is find an
> opportunity to ask one of those people in cars who keep yelling at me
> whether they're familiar with it...
>
> > Since
> >you did this I assume you found it.
>
> Hmm? Most penalties for offenses under the HTA are only fines, not
> jail time. Unless you meant that now I have something other to do
> than looking for an escape hatch?

No, I simply meant you didn't need to search any more :-)
Bicycles are vehicular traffic, and subject to all the rules, and
are entitled to their space. They are not entitled to ride
abreast. As a practical matter I will not ride closer than about
1 yd/meter from the curb. This gives some escape space.

Many motorists have a peculiar viewpoint. When my daughter was
learning to drive she got impatient with bicycles, and I stomped
on that attitude.

One got me about 20 yrs ago, turning left into me as I understand
from witnesses. I still remember nothing of that whole day, and
have memory gaps here and there. Only bike accident I ever had
since puberty.

Ben Pfaff

unread,
Jun 30, 2002, 3:52:00 PM6/30/02
to
CBFalconer <cbfal...@yahoo.com> writes:

> Many motorists have a peculiar viewpoint. When my daughter was
> learning to drive she got impatient with bicycles, and I stomped
> on that attitude.

No kidding. Check out an incident I had on the road with a car
driver yesterday:
http://www.kuro5hin.org/story/2002/6/30/42121/1775

--
"Give me a couple of years and a large research grant,
and I'll give you a receipt." --Richard Heathfield

Edward G. Nilges

unread,
Jun 30, 2002, 4:04:18 PM6/30/02
to
CBFalconer <cbfal...@yahoo.com> wrote in message news:<3D1EF075...@yahoo.com>...

> Dave Vandervies wrote:
> >
> > In article <3D1E236D...@yahoo.com>,
> > CBFalconer <cbfal...@worldnet.att.net> wrote:
> > >Richard Heathfield wrote:
> > >>
> ... snip ...
> > >>
> > >> It has, at least, turned to programming matters now. Nilges has claimed
> > >> that to program a new application in C would be incompetent and
> > >> unethical; he says malloc is dangerous and should not be used; and he
> > >> has produced C code to prove that he, at least, should not be let loose
> > >> with a C compiler. If you want to know more, tune in yourself. :-)

The problem in critiqueing macho "expertise" is that one needs to have
the courage to "look" bad. My code wasn't that great, because I
hadn't used C since 1995.

However, an expert on C failed to recall a simple fact about
malloc'ing a string (this is the fact that it needs space for the Nul)
in the thread. This expert is Richard Heathfield, the author of C
Unleashed and he unquestionably knows C.

You see, my thesis wasn't that I am a current expert in C. It was
instead to deconstruct the notion of expertise which fails to
disambiguate the marketing role of the equivalent of a drug company
salesman and the equivalent of a physician.

In this confusion of levels, any discourse about the external
applicability of the "drug" (C) has to be certified by expertise...in
C: as if one could not critique overprescription of Prozac unless one
worked for Lilly.

Note that only in computer science are we so presumed to be neutral
against the evidence of self-interest in other fields.

My thesis was neither affirmed nor refuted by the level of the code.
In actuality, as I write the second solution pair (truth tables in C:
truth tables in object VB) I get rapidly better because learning, and
*a fortiori* relearning, a programming language is trivial as opposed
to computer science, for probably the same anthropological reason that
Western people fail to realize just how rapidly Third World societies
learn Western ways.

My thesis was instead affirmed by the fact that a recognized expert
failed to summon to mind a factoid, the knowledge of which only an
*idiot savant* could be proud, and of a logical type which is absent
in OO VB. This knowledge is the knowledge of a rubbish heap.

Ioannis Vranos

unread,
Jun 30, 2002, 4:10:40 PM6/30/02
to
"Ben Pfaff" <b...@cs.stanford.edu> wrote in message
news:87n0tct...@pfaff.Stanford.EDU...

> CBFalconer <cbfal...@yahoo.com> writes:
>
> > Many motorists have a peculiar viewpoint. When my daughter was
> > learning to drive she got impatient with bicycles, and I stomped
> > on that attitude.
>
> No kidding. Check out an incident I had on the road with a car
> driver yesterday:
> http://www.kuro5hin.org/story/2002/6/30/42121/1775


I have started to feel a bit afraid of Ben...


--
Ioannis

* Ioannis Vranos
* Programming pages: http://www.noicys.cjb.net
* Alternative URL: http://run.to/noicys

Ben Pfaff

unread,
Jun 30, 2002, 4:28:32 PM6/30/02
to
"Ioannis Vranos" <noi...@spammers.get.lost.hotmail.com> writes:

> "Ben Pfaff" <b...@cs.stanford.edu> wrote in message
> news:87n0tct...@pfaff.Stanford.EDU...
> > CBFalconer <cbfal...@yahoo.com> writes:
> >
> > > Many motorists have a peculiar viewpoint. When my daughter was
> > > learning to drive she got impatient with bicycles, and I stomped
> > > on that attitude.
> >
> > No kidding. Check out an incident I had on the road with a car
> > driver yesterday:
> > http://www.kuro5hin.org/story/2002/6/30/42121/1775
>
> I have started to feel a bit afraid of Ben...

(You should read the comment I added below the story.)
--
"I should killfile you where you stand, worthless human." --Kaz

Ioannis Vranos

unread,
Jun 30, 2002, 4:42:47 PM6/30/02
to
"Ben Pfaff" <b...@cs.stanford.edu> wrote in message
news:878z4wt...@pfaff.Stanford.EDU...


Yes, that what you said is real till the time that you decided to make
him get out of the road. That's why i decided to post. :)

CBFalconer

unread,
Jun 30, 2002, 6:45:26 PM6/30/02
to
Ben Pfaff wrote:
>
> CBFalconer <cbfal...@yahoo.com> writes:
>
> > Many motorists have a peculiar viewpoint. When my daughter was
> > learning to drive she got impatient with bicycles, and I stomped
> > on that attitude.
>
> No kidding. Check out an incident I had on the road with a car
> driver yesterday:
> http://www.kuro5hin.org/story/2002/6/30/42121/1775

Ugly. However, as a measure of self-protection, I have long since
learned not to donate any fingers to random motorists (or
others). I don't even curse them without a good escape hatch.
Are you volunteering to star in the next McGyver series?

The fact that he was wearing dealer plates may mean a) it will be
expensive and/or b) he had no business with them and the whole
thing will get him off the road for a good long time. If he was
also drinking that may show up and have many repercussions. Of
course he may also be seriously bent.

Dave Vandervies

unread,
Jul 1, 2002, 2:41:41 AM7/1/02
to
(ObC: It occurs twice in `BICYCLE'.)

In article <3D1F5B69...@yahoo.com>,
CBFalconer <cbfal...@worldnet.att.net> wrote:

>Bicycles are vehicular traffic, and subject to all the rules, and
>are entitled to their space. They are not entitled to ride
>abreast.

Where are you getting this from? In Ontario, at least (and if I'm not
mistaken it's fairly common), it's perfectly acceptable for two vehicles
to share a lane where it's safe to do so. (It's usually only a good idea
(for values of `good idea' that are a strict superset of `safe') where
lanes aren't wide enough for a car to pass a single bicycle and there's
another lane of traffic in the same direction, though.) Filling a lane
by riding two-abreast also discourages drivers of wider vehicles from
passing without completely changing lanes (which is illegal - vehicles
are required to be driven `as nearly as may be practicable' inside a
single lane). (For the same reason, I find it's fairly common to be
passed by a motorcycle in a single lane.)


>Many motorists have a peculiar viewpoint. When my daughter was
>learning to drive she got impatient with bicycles, and I stomped
>on that attitude.

I think that logging a few hundred hours on a motorcycle should be
required before getting a license to drive any other motor vehicle.
That way new drivers would learn to respect the rules of the road
(because their safety depends on it) before they get to drive anything
that's dangerous to others.


dave

--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca
This is terribly embarrassing. But I have an idea which might save the day.
What's that quote from the Tao? "What is appropriate for the master is not
appropriate for the student", or some such. --Richard Heathfield in CLC

Brendan Sechter

unread,
Jul 1, 2002, 3:54:33 AM7/1/02
to
In article <87n0tct...@pfaff.Stanford.EDU>, Ben Pfaff wrote:
> CBFalconer <cbfal...@yahoo.com> writes:
>
>> Many motorists have a peculiar viewpoint. When my daughter was
>> learning to drive she got impatient with bicycles, and I stomped
>> on that attitude.
>
> No kidding. Check out an incident I had on the road with a car
> driver yesterday:
> http://www.kuro5hin.org/story/2002/6/30/42121/1775

Think back on that must be surreal. Your feeling guitly about the incident
tells me that you are not a sociopath.

-Brendan

Richard Heathfield

unread,
Jul 1, 2002, 2:03:30 AM7/1/02
to
"Edward G. Nilges" wrote:
>
> CBFalconer <cbfal...@yahoo.com> wrote in message news:<3D1EF075...@yahoo.com>...
> > Dave Vandervies wrote:
> > >
> > > In article <3D1E236D...@yahoo.com>,
> > > CBFalconer <cbfal...@worldnet.att.net> wrote:
> > > >Richard Heathfield wrote:
> > > >>
> > ... snip ...
> > > >>
> > > >> It has, at least, turned to programming matters now. Nilges has claimed
> > > >> that to program a new application in C would be incompetent and
> > > >> unethical; he says malloc is dangerous and should not be used; and he
> > > >> has produced C code to prove that he, at least, should not be let loose
> > > >> with a C compiler. If you want to know more, tune in yourself. :-)
>
> The problem in critiqueing macho "expertise" is that one needs to have
> the courage to "look" bad. My code wasn't that great, because I
> hadn't used C since 1995.
>
> However, an expert on C failed to recall a simple fact about
> malloc'ing a string (this is the fact that it needs space for the Nul)
> in the thread.
>
> This expert is Richard Heathfield, the author of C
> Unleashed and he unquestionably knows C.

Mr Nilges does me too much honour. Nevertheless, what he fails to
point out is that the code in question was his; it was he, not I,
who failed to recall that simple fact about strings. The sheer
density of his code - it was what a classical musician might call
"black" - made it hard to spot things like that. Mr Nilges
should take responsibility for his own bugs. I refer those who care
to "The Data Quality Act" over in comp.programming, and warn
everyone else to stay well away, for the sake of their free time.

<snip>

Brendan Sechter

unread,
Jul 1, 2002, 4:08:39 AM7/1/02
to
[SNIP]

void
create_node
(
/* Parameters */
)
{
if (/* We need another node */)
{
create_node(/* Parameters */);
}
else
{
sub_main();
/* Or main()? I've never explicitly called main() */
}
return;
}

void
sub_main
(
/* Parameters */
)
{
/* Here we can sort it, etc. */
/* Let us insert a node */
{
create_node(/* Parameters */);
/* A single return deeper in recursion
* will cause a return domino effect.
*/
return;
}
}

How does that look?

-Brendan

Bill Godfrey

unread,
Jul 1, 2002, 5:02:34 AM7/1/02
to
CBFalconer <cbfal...@yahoo.com> writes:

> Exercise for him - build a singly linked list of arbitrary length
> without malloc. Having done it with recursive calls, now reverse
> the list. Then sort it. Delete the median item.

Sure...

calloc()
realloc()

Bill, shouldn't.

CBFalconer

unread,
Jul 1, 2002, 6:30:08 AM7/1/02
to
Dave Vandervies wrote:
> CBFalconer <cbfal...@worldnet.att.net> wrote:
>
> >Bicycles are vehicular traffic, and subject to all the rules, and
> >are entitled to their space. They are not entitled to ride
> >abreast.
>
> Where are you getting this from? In Ontario, at least (and if I'm not
> mistaken it's fairly common), it's perfectly acceptable for two vehicles
> to share a lane where it's safe to do so. (It's usually only a good idea

Note I said "not entitled", not forbidden.

CBFalconer

unread,
Jul 1, 2002, 6:30:13 AM7/1/02
to
Richard Heathfield wrote:
>
... snip ...
> should take responsibility for his own bugs. I refer those who care
> to "The Data Quality Act" over in comp.programming, and warn
> everyone else to stay well away, for the sake of their free time.

My download of that, which I should be getting to momentarily,
suppressed 10 out of 20 new messages this morning. They've been
at it <sigh>.

Mark McIntyre

unread,
Jul 1, 2002, 6:03:14 PM7/1/02
to
On Mon, 1 Jul 2002 06:41:41 +0000 (UTC),
dj3v...@calum.csclub.uwaterloo.ca (Dave Vandervies) wrote:

>(ObC: It occurs twice in `BICYCLE'.)
>
>In article <3D1F5B69...@yahoo.com>,
>CBFalconer <cbfal...@worldnet.att.net> wrote:
>
>>Bicycles are vehicular traffic, and subject to all the rules, and
>>are entitled to their space. They are not entitled to ride
>>abreast.
>
>Where are you getting this from? In Ontario, at least (and if I'm not
>mistaken it's fairly common), it's perfectly acceptable for two vehicles
>to share a lane where it's safe to do so.

In the UK, it is obligatory for horses, bicycles and other slow moving
vehicles to travel in single file unless the road is empty of other
traffic.

>I think that logging a few hundred hours on a motorcycle should be
>required before getting a license to drive any other motor vehicle.

Excellent idea. The pass rate would go up too, because about 50% of
learners would be hospitalised within a few hours (at least in London
they would....) and the ones that were left would be the sensible
drivers.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>

BruceS

unread,
Jul 1, 2002, 6:52:17 PM7/1/02
to
"CBFalconer" <cbfal...@yahoo.com> wrote in message
news:3D1F8A66...@yahoo.com...

> Ben Pfaff wrote:
> >
> > CBFalconer <cbfal...@yahoo.com> writes:
> >
> > > Many motorists have a peculiar viewpoint. When my daughter was
> > > learning to drive she got impatient with bicycles, and I stomped
> > > on that attitude.
> >
> > No kidding. Check out an incident I had on the road with a car
> > driver yesterday:
> > http://www.kuro5hin.org/story/2002/6/30/42121/1775
>
> Ugly. However, as a measure of self-protection, I have long since
> learned not to donate any fingers to random motorists (or
> others). I don't even curse them without a good escape hatch.
> Are you volunteering to star in the next McGyver series?
>
> The fact that he was wearing dealer plates may mean a) it will be
> expensive and/or b) he had no business with them and the whole
> thing will get him off the road for a good long time. If he was
> also drinking that may show up and have many repercussions. Of
> course he may also be seriously bent.

Bent? Really? Just because he tried to use a car to kill someone who had
clearly offended him? You judge a bit harshly there.
Great story, Ben. You'll probably get a few folks upset over this one. In
real life, however, I agree with Chuck, that you shouldn't salute drivers.
Recently in Denver (The Mile High Cow Town), a man was convicted of murder
after he shot a bicyclist to death for complaining about his dangerous
driving.

Dave Vandervies

unread,
Jul 2, 2002, 4:57:01 PM7/2/02
to
In article <3D2023FD...@yahoo.com>,

CBFalconer <cbfal...@worldnet.att.net> wrote:
>Dave Vandervies wrote:
>> CBFalconer <cbfal...@worldnet.att.net> wrote:
>>
>> >Bicycles are vehicular traffic, and subject to all the rules, and
>> >are entitled to their space. They are not entitled to ride
>> >abreast.
>>
>> Where are you getting this from? In Ontario, at least (and if I'm not
>> mistaken it's fairly common), it's perfectly acceptable for two vehicles
>> to share a lane where it's safe to do so. (It's usually only a good idea
>
>Note I said "not entitled", not forbidden.

I seem to be completely failing to get what you mean by `not entitled'.
Is it possible we're in violent agreement here?


dave

--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca
> Where does the break belong?
The bit bucket.
--Peter Pichler and Richard Heathfield in comp.lang.c

Dave Vandervies

unread,
Jul 2, 2002, 5:06:47 PM7/2/02
to
In article <slrnai03g7...@granicus.if.org>,

Brendan Sechter <sg...@granicus.if.org> wrote:
>In article <3D1EF075...@yahoo.com>, CBFalconer wrote:

>> Very good. I didn't claim any impossibility though. Actually the
>> building is the hardest part. It does have the advantage of never
>> waiting around for malloc/free :-) To make it harder I should
>> have added an insertion somewhere. The limits are going to be
>> much smaller than with malloc as many implementations limit stack.
>[SNIP]
>
>void
>create_node
>(
> /* Parameters */
>)
>{
> if (/* We need another node */)
> {
> create_node(/* Parameters */);
> }
> else
> {
> sub_main();
> /* Or main()? I've never explicitly called main() */
> }
> return;
>}

You need some way to get the created nodes out; passing them to sub_main
would be the obvious way to do so.


>void
>sub_main
>(
> /* Parameters */
>)
>{
> /* Here we can sort it, etc. */
> /* Let us insert a node */
> {
> create_node(/* Parameters */);
> /* A single return deeper in recursion
> * will cause a return domino effect.
> */
> return;
> }
>}
>
>How does that look?

The hard part is having sub_main do The Right Thing on appropriate calls.
The easiest way to do that is to pass all its local state down the call
tree through create_node; since if you do that you end up having to check
where you want to continue and running that bit of code, it's simpler to
write a function for every continuation and just pass a pointer to the
appropriate function to create_node, and have create_node call through
that pointer.
This would be made much easier if it were possible to create an object
that could be called through as if it were a function pointer that would
call the function it was created in with the same local variable values
and current statement as when it was created; this is why I was talking
about Scheme's call/cc elsethread (since that's exactly what it does,
modulo differences with heap/stack allocation of local variables and
tail call optimization).


dave

--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca

Brendan Sechter

unread,
Jul 4, 2002, 1:45:52 AM7/4/02
to
In article <aft4l7$6ju$2...@tabloid.uwaterloo.ca>, Dave Vandervies wrote:
> In article <slrnai03g7...@granicus.if.org>,
> Brendan Sechter <sg...@granicus.if.org> wrote:
>>In article <3D1EF075...@yahoo.com>, CBFalconer wrote:
>
>>> Very good. I didn't claim any impossibility though. Actually the
>>> building is the hardest part. It does have the advantage of never
>>> waiting around for malloc/free :-) To make it harder I should
>>> have added an insertion somewhere. The limits are going to be
>>> much smaller than with malloc as many implementations limit stack.
>>[SNIP]
>>
>>void
>>create_node
>>(
>> /* Parameters */
>>)
>>{
>> if (/* We need another node */)
>> {
>> create_node(/* Parameters */);
>> }
>> else
>> {
>> sub_main();
>> /* Or main()? I've never explicitly called main() */
>> }
>> return;
>>}
>
> You need some way to get the created nodes out; passing them to sub_main
> would be the obvious way to do so.

create_node() always calls either sub_main() or create_node().

>>void
>>sub_main
>>(
>> /* Parameters */
>>)
>>{
>> /* Here we can sort it, etc. */
>> /* Let us insert a node */
>> {
>> create_node(/* Parameters */);
>> /* A single return deeper in recursion
>> * will cause a return domino effect.
>> */
>> return;
>> }
>>}
>>
>>How does that look?
>
> The hard part is having sub_main do The Right Thing on appropriate calls.
> The easiest way to do that is to pass all its local state down the call
> tree through create_node;

I used:

/* Parameters */

in my pseudocode for a reason. One could do that. I would make sub_main()
interactive, but there are alternatives. (Interactive is not always
suited to a given task.)

> since if you do that you end up having to check
> where you want to continue and running that bit of code, it's simpler to
> write a function for every continuation and just pass a pointer to the
> appropriate function to create_node, and have create_node call through
> that pointer.

I'd probably use a pointer to a task stack and a switch statement. One
could opt for a task stack that is an array of pointers to functions.

> This would be made much easier if it were possible to create an object
> that could be called through as if it were a function pointer that would
> call the function it was created in with the same local variable values
> and current statement as when it was created;

I think that is some version of a run on sentence. It is very hard to
parse. You could use structures that you pass via pointer to function.
This way all functions can use all the data.

> this is why I was talking about Scheme's

Never tried scheme.

> call/cc elsethread (since that's exactly what it does,
> modulo differences with heap/stack allocation of local variables and
> tail call optimization).

I think it is time for me to learn something. What is a tail call?

-Brendan

Dave Vandervies

unread,
Jul 4, 2002, 6:15:09 AM7/4/02
to
In article <slrnai7o8g...@granicus.if.org>,

Yep. But you'd want it to call sub_main(/*parameters*/) (where
/*parameters*/ includes a pointer to the head of the list), and not just
sub_main(), to get the newly-allocated-on-stack links into the code that
actually uses them.
(Yes, I know, nitpicking pseudocode was probably a Bad Idea.)


>>>void
>>>sub_main
>>>(
>>> /* Parameters */
>>>)
>>>{
>>> /* Here we can sort it, etc. */
>>> /* Let us insert a node */
>>> {
>>> create_node(/* Parameters */);
>>> /* A single return deeper in recursion
>>> * will cause a return domino effect.
>>> */
>>> return;
>>> }
>>>}
>>>
>>>How does that look?
>>
>> The hard part is having sub_main do The Right Thing on appropriate calls.
>> The easiest way to do that is to pass all its local state down the call
>> tree through create_node;
>
>I used:
>
>/* Parameters */
>
>in my pseudocode for a reason. One could do that. I would make sub_main()
>interactive, but there are alternatives. (Interactive is not always
>suited to a given task.)

Interactive isn't suited to the task as given, which was just `do these
operations'.

Passing all the state information needed back down to sub_main as function
arguments works (and is the best we have in C), but it fgets Ugly.
See below for my comments on a better way (that actually exists, just
not in C).


>> since if you do that you end up having to check
>> where you want to continue and running that bit of code, it's simpler to
>> write a function for every continuation and just pass a pointer to the
>> appropriate function to create_node, and have create_node call through
>> that pointer.
>
>I'd probably use a pointer to a task stack and a switch statement. One
>could opt for a task stack that is an array of pointers to functions.

Hmm... that would work, though I'm not sure it's any simpler than just
passing a single variable representing `what to do next' that makes its
way back to the function.


>> This would be made much easier if it were possible to create an object
>> that could be called through as if it were a function pointer that would
>> call the function it was created in with the same local variable values
>> and current statement as when it was created;
>
>I think that is some version of a run on sentence. It is very hard to
>parse. You could use structures that you pass via pointer to function.
>This way all functions can use all the data.

OK, let me try to break that sentence down.

The way I wrote the code passes a pointer to a function to the
node-creating function, and then the node-creating function calls the
function that its caller wants called through that pointer.
So we have:

--------
/*I don't like typedefs, but they make function pointers easier to grok*/
typedef return_type (*FUNCTYPE)(struct link *,magic_args);

return_type create_node(struct link *oldhead,magic_args args,FUNCTYPE func_to_call)
{
/*Do magic to create nodes*/

return func_to_call(newhead,args);
}
--------

Here, instead of writing the function to call into create_node, we give
it a pointer to a function and have it call that function; this makes
it more flexible, since we can say
--------
return_type stage_1(struct link *head,magic_args args)
{
/*Do some stuff*/
return create_node(head,args,stage_2);
}

return_type stage_2(struct link *head,magic_args args)
{
/*Do some more stuff with newly-created nodes we got from create_node*/
return the_final_value;
}
--------
which lets us separate the different actions into different functions,
which can be cleaner than doing
--------
return_type do_everything(struct link *head,magic_args args)
{
switch(args.what_next)
{
case DO_STUFF1:
/*do some stuff*/
return create_node(head,args);
case DO_STUFF2:
/*do some more stuff*/
return the_final_value;
}
}
--------
and packing everything into one function like we'd have to do if
create_node always called the same function when it was done.

So far this is all C. From here I'm getting a bit (and eventually a
lot) off-topic.

It would be Really Cool if we could, instead of passing a pointer to
another function, pass something that acted like a function pointer but
brought us back to where we were in the function instead of invoking
another function when create_node called it at the end:
--------
return_type do_everything_the_easy_way(struct link *head,magic_args args)
{
/*do some stuff*/
create_node(head,args,the_magic_func_pointer);

/*Since we passed create_node the magic sort-of-a-function-pointer,
when it calls `func_to_call(newhead,args)' control goes here:
*/
/*do some more stuff*/
return the_final_value;
}
--------
Doesn't this look a lot cleaner than messing around with switch statements
or multiple functions? It fgets even better when we want to do it in a loop:
--------
return_type more_easy_way(struct link *head,magic_args args)
{
for(i=0;i<some_value;i++)
{
/*Do some stuff*/
if(need_to_add_links)
{
create_node(head,args,the_magic_func_pointer);

/*Do some stuff with the new links*/
}
}
return the_final_value;
}
--------
(Try doing this (maintaining the loop nature) with either a switch
(your idea) or a set of functions and pointers to them (my idea) -
it can be done, but it's Extremely Ugly.)

(Remember that the whole reason we're doing this in the first place is
that we're trying to create links in our linked list without using malloc,
so we have to keep going down the call tree and have create_node create
a link on the stack every time it's called. The obvious way to do it
in C is to have create_node malloc nodes (on the heap) and pass them
back up the call stack, but that's forbidden by the constraints we're
working under.)

It would be even nicer if the magic sort-of-a-function-pointer saved all
the local variables and restored them along with the current statement
when it was called, so that we didn't have to bother create_node with
the magic args that we're passing the function state through, and we'd
just get back to our function with a few more links on the stack.

C doesn't have anything of the sort (and it would be highly nontrivial
to implement, for various reasons), but basically the idea is that we
encapsulate the current state of the function so that we can return there
instead of going back to the top of the function (and possibly checking
some bit of information passed in to see what to do next, and by doing
that going back to where we left off) or calling a different function
(again, always going to the top of that function, and possibly from
there deciding where we left off and going back there).


>> this is why I was talking about Scheme's
>
>Never tried scheme.
>
>> call/cc elsethread

You should try it sometime; it's a lot of fun. Feel free to email me
for some examples of things that it makes easier and/or more interesting
than other languages, but I'll try to stay at least within the bounds
of normal topic drift here.

One of the things that it makes both easier and more interesting is
that it has a way to create the magic function pointers I was referring
to above, and they work exactly the way you'd want them to - you pass
the continuation to another function, and that function can call the
continuation and control passes back to the point where the continuation
was created.

>> (since that's exactly what it does,
>> modulo differences with heap/stack allocation of local variables and
>> tail call optimization).
>
>I think it is time for me to learn something. What is a tail call?

A tail call is a function call call where the function making the call
returns the value returned by the function called directly, without
doing anything else with it:
--------
int foo(void)
{
int i;

i=this_is_not_a_tail_call();

return this_is_a_tail_call(i);
}
--------
(or just:
--------
int foo(void)
{
return this_is_a_tail_call(this_is_not_a_tail_call());
}
--------
).

In C (and most other languages as well), this is implemented (except
in a few special cases that the compiler can recognize and optimize)
by having the function do something like:

Call function that makes tail call
Create stack frame for function that makes tail call
Do non-tail-call stuff
Call tail-called function
Create stack frame for tail-called function
Do tail-called function stuff
Clean up stack frame for tail-called function and return value to
function that makes tail call
Get value from tail-called function
Clean up stack frame for function that makes tail call and return value to
its caller
Get value from function that makes tail call

By doing something like this, you can't do something like what we're
talking about above for very long before you overflow your stack, since
you have a bunch of stack frames that are mostly useless (all they do
is keep passing the same value back up); it would be better (and Scheme
requires this, which is another reason why it's useful for what I was
describing) if it would do:

Call function that makes tail call
Create stack frame for function that makes tail call
Do non-tail-call stuff
Mangle stack frame so that tail-called function returns directly to caller
of function that makes tail call
Transfer control to tail-called function
Do tail-called function stuff
Clean up stack frame for tail-called function and return value to caller
of function that makes tail call
Get value "from function that makes tail call" (but really it came directly
from tail-called function)

(An obvious way to do this is to allocate activation records (which are no
longer "stack frames") on the heap instead of the stack and release them
(either explicitly or by letting the garbage collector pick them up)
after copying the `where the value is going' into the new activation
record when making a tail call.) When you're doing this, you can have
arbitrarily many tail calls live at the same time without running out of
stack space (or space wherever you're allocating your activation records).

Going further off on my tangent, it's possible to write (in a language
that supports proper tail-call optimization and some way of passing a
representation of a function to another function) a program that never
actually returns from a function except at the very end (and even that can
be avoided by ending with calling the equivalent of exit()), but where
every function receives as an argument a function for `what to do next'
and tail-calls that function instead of returning. There are a lot of
reasons, most of which I don't understand, why this is an interesting and
useful thing to be able to do, but one of the reasons that I do understand
is that it makes expressing something like `allocate stuff that needs
to be somewhat persistent "on the stack"' a bit easier to express (as
I did in my example), at least once you understand what's going on.


ObC: The reason I'm so interested in this is because writing a Scheme
interpreter (which needs to make it possible to do these things) is my
current project-that-it-would-be-cool-to-do-instead-of-just-thinking-
about-it. This interpreter, if it ever happens, will be written in C.


dave

--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca
> That's about the worst piece of advice I have ever read.
Oh, no one ever suggested that you become a sysadmin?
--Peter Lemken and David P. Murphy in the scary devil monastery

0 new messages