Wednesday, December 07, 2005

T&L - Not Made For Each Other?

---------------------------------
THREADS AND LIBRARIES
NOT MADE FOR EACH OTHER?
---------------------------------

1 INTRODUCTION

Threading libraries hide very little of the complexity involved in the use of threads. Often, the focus and the major obstacles in implementing a multithreaded system are the low-level details of threading, rather than the problems that the system is designed to solve.

Objects can be said to model reality, thereby providing good abstraction. However, a crucial part of reality that is not represented adequately in an object is a sense of time. Objects exist in time and space, and interact with other objects; they have "life". A mechanism for intuitively expressing such Live Objects (or Active Objects), where an object has its own thread, is missing from the threading libraries in (libraries of) object-oriented languages today.
Spatial representation OK.
Temporal representation, not OK.
2 CURRENT THREADING MECHANISMS

Presently to use threads, we create a thread and give it sections of code (from the object) for it to do. For example,

threadHandle=CreateThread(StuffToDo , OS/LibraryParameters)

is how threads of control are created from the program. The code (StuffToDo) is then executed in the newly created thread.

2.1 Observations

In the present library implementations,

2a Threads use objects.
The thread executes a function, possibly a function or method of an object. In the example, StuffToDo could be the method of an object.

2b Threads are to functions what objects are to classes.
Or, threads are objects. The thread object instantiates a function, brings into execution-space so to say, executing it. The implementation forces the thread to become a first-class "object" in the program-space. It has a handle, threadHandle, that can be used to refer to it.

2c Threads are almost equivalent to operating system threads.
Most of what can be done with an operating system thread can be done with library threads also - one can suspend a thread, resume it, abort it etc

3 'OBJECT'IONS - CRITIQUE

In the real world, entities use their time and their resources to do things. A thread can be viewed as a flow of time for practical purposes. In the library-model, threads use objects (2a) whereas in reality, objects use threads. This unnatural modeling contributes to the difficulties of conceptualizing and implementing threaded systems.

It should be "Objects use threads",
not "Threads use objects".

An object oriented program/system is an exchange of messages between objects resulting in side-effects useful towards the solution of the problem at hand. Thread objects (2b) are only an implementation mechanism, a way of calling a function; they do not help to manage complexity. Instead, thread object interactions add complexity and intrude on the main logic of the program.
In the scenario of single-threaded program development, come to think of it, the programmer plays the role of the thread object during coding- deciding which functions to call and in what order. Sadly though, this does not scale - which is why multithreaded programs are so challengingly complex.
Why have thread objects at all in programs? Threads are, very much, operating system entities (2c) . If we have the thread object in the program, it is only natural that they have methods similar to the real-world (albeit on the OS-side) entities that they model, with some high-level constructs thrown in for good measure. If we have thread objects, the complexity of threading cannot be hidden from the programmer.
For operating systems, threads are expensive to manage. The objection to live objects that is raised all too often is: "What! If I have a 1000 live objects, it would mean 1000 threads too? You must be out of your mind..." This mental block must be removed. The programming language back-end (the popular idiom of the runtime) can possibly be adapted to meet the external implementation constraints.
Hide the complexity of threads from the programmer, effectively.
4 OOTOPIA
Ideally, after the definition of live objects, one would be able to program like a classroom interaction like this:
void main()
{
TeacherLiveObject theProf;
StudentLiveObject theStudents[30];
}
That would be it?
5 CONCLUSION

A LOOP (Live Object Oriented Programming) language is the need of the hour. Such a language would help people to take their minds off low-level threading details and focus on more domain-relevant issues at hand, enabling the construction of more useful programs.

- Thomas Jay Cubb


External links
1 The Free Lunch Is Over
2 Software and the Concurrency Revolution
3 Discussion on Active Objects In Python
4 IBM Research- The X10 Programming Language - A LOOP language?
5 Polyphonic C# in Cw - Another LOOP language?

Tuesday, December 06, 2005

Cline's Commandments

* A class Fred's assignment operator should return *this as a Fred& (allows
chaining of assignments)
* A class with any virtual[20] functions ought to have a virtual
destructor[20.4]
* A class with any of {destructor, assignment operator, copy constructor}
generally needs all 3
* A class Fred's copy constructor and assignment operator should have const in
the parameter: respectively Fred::Fred(const Fred&) and
Fred& Fred::operator= (const Fred&)
* When initializing an object's member objects in the constructor, always use
initialization lists rather than assignment. The performance difference for
user-defined classes can be substantial (3x!)
* Assignment operators should make sure that self assignment[12.1] does
nothing, otherwise you may have a disaster[12.2]. In some cases, this may
require you to add an explicit test to your assignment operators[12.3].
* In classes that define both += and +, a += b and a = a + b should generally
do the same thing; ditto for the other identities of built-in types (e.g.,
a += 1 and ++a; p[i] and *(p+i); etc). This can be enforced by writing the
binary operations using the op= forms. E.g.,

Fred operator+ (const Fred& a, const Fred& b)
{
Fred ans = a;
ans += b;
return ans;
}


This way the "constructive" binary operators don't even need to be
friends[14]. But it is sometimes possible to more efficiently implement common
operations (e.g., if class Fred is actually String, and += has to
reallocate/copy string memory, it may be better to know the eventual length
from the beginning).

Sunday, December 04, 2005

ISO C++ updates

A static const integer member is the one instance in C++ in which a class member can be initialized explicitly within the class definition, thereby making the value available to other constructs within the class, such as the dimension size of m_buffer. Without this construct, the use of an enumerator as a symbolic constant was a common workaround.

There is now covariant return type support in the definition of virtual functions. This is great news for those who write class hierarchies.

There is support for the implicit return of 0 within main.

Tuesday, November 29, 2005

Heart For The GNU

This short poem tries to encapsulate some Linux history.

Linus Torvalds wanted to modify Andrew Tenenbaum's MINIX operating system initially. But Tanenbaum did not give him permission, so he set about writing his own operating system. This became the kernel for the GNU project which aimed at making a free operating system.

--------------------------------
A HEART FOR THE GNU
--------------------------------
Tanenbaum forbade,
Linus obeyed.
Fiat Linux!
Freedom redux.

- Thomas Jay Cubb


Notes
--------
1. "Fiat Lux" is a Latin phrase meaning "let there be light" from the Bible's Genesis book which relates God's creation of the world. Linus, the Creator! So, Fiat Linux.
2. redux = Brought back. The GNU OS project was losing steam and face, for the lack of a suitable kernel for its operating system. The Linux kernel, so to say, resurrected it. (GNU/Linux)


You may also be interested in reading Punnix.

Monday, November 28, 2005

On The Hacked Track

1. Viewing the dependencies of a binary
ldd gives you the dynamic libraries that a file depends on.
$ ldd binaryfile

2. Viewing the symbols in a file
nm gives you the list of symbols in the file. Functions that are exported by the library will be present as symbols. Many files are stripped of symbols before they are released, though.
$ nm binaryfile/libraryfile

3. Interposing
On many *NIX variants, you can set a dynamic library of your choice to be searched first when dynamic library calls are made.
Set the value of LD_PRELOAD to the full path of the library file you want to be executed in preference to other libraries.

Take an executable and determine its dependencies. View the symbols in those library-files. Make your own library-file with implementations for the symbols that seem to be of relevance to you. Set the LD_PRELOAD variable to the name of your library file. Run the executable.


Tuesday, November 22, 2005

Data Polymorphism

INTRODUCTION
----------------------------

Languages that support polymorphism seem to require functions to model polymorphic requirements. This suffices in most cases, but there are cases in which it is only the data that is polymorphic - what takes a different form in a different context.

While modeling data polymorphism is possible through the use of templates (will be discussed in a later post), this article makes a case for the language to allow interfaces to have abstract data members, whose types are unknown in the base class and will be meaningful only in the derived context.

Interfaces (and Abstract Base Classes) are an expressive notation for mandating the implementation of required functions in derived classes. Why not utilize the same notation to accommodate data as well?

In a nutshell, the following is possible :-

class Abstract
{
virtual void pureVirtualFunction()=0; //Unknown behaviour, specifiable
void concreteFunction()
{
pureVirtualFunction(); // We can call the undefined function
}
};

But the following is not :-

class Abstract
{
virtual pureVirtualData; //Unknown data, Not allowed

void concreteFunction
{
print pureVirtualData.Count; // We know how to use the data though
}

};

What does this imply? Could there be cases where such a feature would help?

Some months back, I encountered a requirement which, I thought, really called out for more direct support for data polymorphism in the language. I explain the problem in a generalized way, leaving out some domain-specific details.

Please do let me know if more details are needed to understand the problem and why the limitations mentioned are significant.

THE REQUIREMENT
--------------------------------

An algorithm needs to be implemented on the transmissions of an existing client-server system to improve its performance. Broadly, the algorithm transparently intercepts the packets, applies some transforms based on the packet and relays them.

In order to implement the algorithm, components should be deployed at both the server and the client. The algorithm depends on the functionality in a packet and a factor which is determined by whether the component is at the server or at the client.

DESIGN WITH BEHAVIOURAL POLYMORPHISM
----------------------------------------------------------------------

Packet is a concrete class which provides a buffer-storage area and some domain-specific functionality.

class Packet
{
Byte Buffer[];

virtual double toDouble();
virtual int toInteger();


void applyXXXToPacket()
...//Other domain-specific functions
...
};
The algorithm depends on Packet functions to transform the packets with a factor which is based on Packet::toDouble() and on Packet::toInteger(). Both these conversions are to be done slightly differently from the implementations in the Packet class and, also, differently at client- and server- sides.

We have the inheritance,
ServerPacket: public Packet, and we reimplement toInteger and toDouble for server
ClientPacket: public Packet, and we reimplement toInteger and toDouble for client

Algorithm components only need to apply some transforms on Packets. We generalize to the abstraction,
class AlgorithmComponent
{
Packet& p; //Reference type required to achieve behavioural polymorphism

void ProcessPacketXXX();
... //Functions which use Packet::functions
... //
};

The component implementing the algorithm only differs slightly on the server and client sides. But they do differ and so we have the specializations,

ServerComponent: public AlgorithmComponent
ClientComponent: public AlgorithmComponent

It worked! But...

PERFORMANCE ISSUES...
--------------------------------------

It turned out that both the required conversion functions were very expensive, leading to erratic performance. All that was really required was a one-time computation of the conversion, which could be done in the constructors of the specialized Packets. Saving these in a member variable would solve the performance issues.The ClientComponent and the ServerComponent could then use this saved value directly.

But it is not possible to for the generalized AlgorithmComponent to access a data member of the generalized Packet class through a Packet reference and get the implementations of the derived classes.

Consider the code snippet below.

class Base{
public:
int i;
Base(){i=2;} //In B, i is 2
};
class Derived:  public Base
{
public:
int i;
Derived(){i=5;} //In D, i is 5

};

void main()
{
Derived d;
Base& b=d;
cout << class="cpp-comment">//Prints 2, not 5. No polymorphism for data access. :-(
}

This means that the abstraction of AlgorithmComponent would collapse - breaking the class hierarchy.

...AND A TRIVIAL(?) VIOLATION OF A DESIGN CONSTRAINT
------------------------------------------------------------------------

An AlgorithmComponent necessarily has to be either server-side or client-side. It was just an abstraction of design which accurately summarized the operation of the algorithm. AlgorithmComponent should not be instantiable, it is an abstract base class by nature.

Implementing this particular design constraint is possible if we make the functions which depend on Packet pure virtual. Technically, for AlgorithmComponent to be abstract, we need to make only one of the ProcessPacketXXX()s pure virtual. But that would not accurately model the dependency on Packet for the other functions.

Functions that depend on Packet can be completely specified. We could avoid code duplication if we code it in the base class itself. The abstractness of AlgorithmComponent is because of its dependency on Packet. So, Packet is what should be pure virtual really.

What we should have had was an AlgorithmComponent with completely specified functions but with an unspecified Packet that had to be compulsorily supplied by the derived class.

CONCLUSION
----------------------

What if, in the discussed example, ServerComponent depended on a double/class Foo and ClientComponent depended on an int/class Bar? Shouldn't abstract base classes be allowed to have undefined data members? Or equivalently, why not allow data members in interfaces?

Workarounds to these do exist -
1) with templates (the discussion stopped just short of it, don't you think?) - but it would be a compile-time solution. Will be discussed in a later post.
2) with composition instead of inheritance (which is how we chose to implement it finally) -but lacks the simplicity and elegance of the explained design - with code duplication and what not.

Would it not be simpler and cleaner to express such a design if the language just allowed the data also to be truly polymorphic?

- Thomas Jay Cubb

Monday, November 21, 2005

Everything Changes

-------------------------------
EVERYTHING CHANGES
-------------------------------

Systems are built to satisfy the requirements of users. Successful systems -
a) meet those requirements and,
b) will continue to be used by the users, who would prefer it to any other.

It is possible for a system to succeed even if it is not flexibly designed. My system does the job and they like it! These are the requirements, my system is designed for that! Who cares that it is not flexible! I have done the requirement-collection to perfection. There's nothing more they could possibly want!

Now who wouldn't want his system to be successful? In fact, most people would want their creation to be indispensable! But with great power, comes great responsibility. Good design is all the more essential if your system has even the remotest chance of being successful - if you want to be a star, not just a shooting star.

Successful systems will be used by the users and, over a long period of time. Any successful system will, in the course of its lifetime, be required to accommodate changes. No matter how well you did the requirement-collection, over time, the set of users will change and by extension, the requirements too! All of a sudden your "successful" systems becomes a failure. Users choose to switch from the system

We must be able to adapt and quickly at that. Accommodating new requirements or changing the behaviour should not become an unnecessarily complex or time-consuming chore - requiring the complete revalidation of the system. Resilience to change is one of the hallmarks of a good design.

Changes in a system may be required because -
a) The users of the system have new requirements. Wouldn't it be cool if this thing could do that as well?... I want to use my credit-card to pay..... or ... I want this bus to fly!
b) Better, more suitable ways of doing things may emerge only after the system is deployed. Would it not be better and simpler to do it like this?... I want the system to start when I press the end button...
c) There were slight errors in our understanding of the requirement. Largely unavoidable. Because only hindsight is 20/20. Oh, was that the order in which you wanted things to happen?... The person should be given the receipt before he pays....

While bus-to-airbus scenarios are well-nigh impossible to design for, with a little bit of thoughtful design, the other two can be designed for more easily. What's more, often you will find that many of the seemingly bus-to-airbus requirement-changes could have been handled in less cumbersome ways, if only you had thought about possible changes during design.

-Thomas Jay Cubb

Wednesday, November 16, 2005

SunOS vs Solaris

What's the difference between SunOS and Solaris?

SunOS refers to the actual operating system that underlies the Solaris OE (operating environment). SunOS is often used to refer to the old SunOS 4.x, a BSD-like operating system with some SVR4 features and OpenWindows.

Solaris is typically used to refer to SunOS 5.x releases of the operating system and environment from Sun Microsystems. The version of Solaris can be derived from the SunOS 5.x designation by dropping the leading 5. e.g., Solaris 7 is SunOS 5.7. However, some earlier verions of Solaris were numbered as 2.5.1 with a SunOS release of 5.5.1.

Monday, November 14, 2005

Peter Deutsch's Eight Fallacies

Picked this up from digg.com

-----------------------------------------------------
The eight fallacies of distributed computing
By Peter Deutsch
-----------------------------------------------------

Essentially everyone, when they first build a distributed application, makes this eight assumptions.
All prove to be false in the long run and all cause big trouble and painful learning experiences.

1. The network is reliable
2. Latency is zero
3. Bandwidth is infinite
4. The network is secure
5. Topology doesn't change
6. There is one administrator
7. Transport cost is zero
8. The network is homogeneous

Thursday, November 10, 2005

Finding Bliss - UNIX find Introduction

----------------------
FIND-ING BLISS
----------------------
The UNIX find command is, in my book, one of the most powerful time-saving utilities ever. I would even go so far as to say that you have not appreciated the power of UNIX utilities fully unless you have used, and can habitually use, the find command.

What's more, it it offers great flexibility and power. Not only does it allow you to find stuff, but it also allows you to invoke a command you specify, on each item it finds.

STEP-BY-STEP EXAMPLES
-------------------------------
1. Finding stuff
$ find /
gives you a list of everything that's under the / directory. And that, as far as your system is concerned is everything under the sun. You can replace / with any other directory of your choice.

2. Finding a file based on name
$ find / -name foo
finds all items (files and directories) named foo, on your system. You can specify wildcards if you wish but remember to escape shell expansion for the wildcard by using quotes.

3. Getting a list of all directories on your system
$ find / -type d

4. Executing a command on what find found
$ find / -exec ls -l '{}' \;
generates a detailed ls listing of each item found in the system

This needs a little bit of explanation -
-exec specifies that what follows is a command
\; denotes the end of the command
'{}' is where the current item gets substituted in the command for each item.
You can give any command you want instead of ls, of course.

NOTES
---------
1. -name, -type and -exec are like extensions to the basic find utility, which builds a list of everything under a directory. It spiders the subdirectory structure and builds a list.

2. Think of -name and -type as filter conditions for cutting the list down to just what we need. For example, -type f means files and -type d means directories.

3. -exec specifies the action to invoke on each item - whatever is between exec and \; gets taken by find as the command.

4. There are many more modifiers. Please refer to the man pages on your system. These only serve as quick but useful intros.

PUTTING IT ALL TOGETHER
----------------------------------
Let's say you want to view and edit all readme files under a directory, say, /home using an editor, say vi. Think about it.

You can accomplish this in one line with the find command.
$ find /home -type f -name readme.txt -exec vi '{}' \;

So much less troublesome, less strenuous and less time-consuming than getting a list of the files and clicking on them one by one. All in a line's work!

ON THE DESIGN
(external view)
---------------------
find allows you to iterate over a filtered collection invoking a specified action. Call it... I'm-making-it-up....the Moulding Iterator design pattern if you will. I have found that this is an extremely common problem, it deserves a name, so forgive me!

find epitomizes the engine-addon idiom. At its heart, it is a list generator which has the capability of spidering directory structures. The list generator has unobtrusive facilities for filter conditions, to be used if needed and specifying the action to , if needed. Unobtrusive: if you want the feature, you can use it; if you don't care about it, no need to bother even knowing about it.

Flexibility=Good design. find has its limits, yes, but considering the fact that it was designed when it was, it's very, very good indeed. find out for yourself!

- Thomas Jay Cubb

Sunday, November 06, 2005

Printing Call-Stack Tracebacks

pstack on Solaris gives you a stack dump for all active threads. But this might be too heavy for some applications.

libunwind is a Linux library that provides stack unwinding routines.

The link below gives a method of doing it with functions on Solaris.
techno's scratchpad: C/C : Printing Stack Trace with printstack() on Solaris
But this works only for Solaris 9 onwards...

Check this for some Linux info
http://www.codecomments.com/archive286-2004-7-236422.html

For Windows information
http://www.codeproject.com/threads/StackWalker.asp
Homepagehttp://blog.kalmbachnet.de

Saturday, October 22, 2005

Abstract Class


class AbstractClass
{
public:
void bar();
virtual void foo() = 0; //function not defined
AbstractClass();
virtual ~AbstractClass();

};

void AbstractClass::bar()
{
foo(); //calling the undefined function
}


This code will compile.

Friday, October 14, 2005

Why not CON?

Received a forward today.

>An Indian discovered that nobody can create a folder anywhere named as
>"con "

>This is something pretty cool...and unbelievable... At Microsoft the whole
>team, including Bill Gates, couldn't answer why this happened! Try it out
>yourself...


The first part of the excerpt is true. But the second is probably (I hope) an exaggeration!

The reason for the restriction is that CON is the special name for the computer-console in DOS and the command-shell. CON is a device name; to create a file from the command-line, we would say COPY CON filename and then type the contents of the file, stoppping with a Ctrl-Z (the DOS end of file indicator) and pressing ENTER. And because filenames are case-insensitive, no variant of CON will be allowed.

Other names not allowed as file/folder-names include: PRN, LPTx, COMx - all device-names.
But interestingly for COMx, even if you have 4 COM ports, COM5, COM6 etc aren't allowed!!! So, does this mean Windows won't allow more than 9 COM ports??? Why not? That would be the real restriction!!!

Tuesday, October 04, 2005

Finding the space gobblers

Find out top 10 directories eating up your disk space:
du -cksh * | sort -rn | head -10

Google And The Truth

"Google first, think later. " is the mantra that everybody, especially the software professional, lives by.

1. There is a problem.
2. Nothing new under the sun.
3. It must have been faced by someone else too.
4. Somebody must have solved it back then.
5. Why reinvent the wheel?
6. Let's get it solved. ... fast.

In this age of instant karma and instant nirvana, the top search result is what becomes the objective truth for the vast majority..

What cannot be found might as well not exist. - TJ

Tuesday, September 20, 2005

Punnix Version 1.2.0

--------------------------------------------------------------------
PUNNIX Version 1.2.0, or a song of Linux

-Thomas Jay Cubb
Note: All puns are intended, but may not be indented!
-------------------------------------------------------------------
Trapped behind closed gates, windows
I was looking for a way out
Of the morass of proprietary property.
‘Cos I was buried by the hefty software bills.
I wondered, why should I
be a slave to that GUI ?

Proprietary software and operating systems place restrictions on your use of them. You might have bought it but it's still not yours! You are not free to use it like you would want to or tailor it to your requirements.
GUI, usually pronounced as “gooey”, is to be pronounced as “guy” here for both rhyme and meaning.


And then in an epiphany,
The flightless angel Tux,
(Or perhaps it was a friendly gnome?)
He showed me the way to a universe
Of Enlightenment,
Home of users (e)X-Windows.

GNOME, which stands for GNU Network Object Model Environment, is a desktop environment usually bundled with Linux. A gnome is also a magical being that guards treasure (how true!!).
Epiphany is a web-browser for GNOME.

Tux is the name of the Linux mascot – that cute penguin.
`The X Window System’, commonly referred to as just `X’, is (generally) the graphical environment for Linux.
Enlightenment is a window-manager for X.
The magic-mantra
say perforce
Floss! Open Source!
Lilo! Behold
A free GNU world unfold.
A la Ali Baba
I could not but gawk
At the unhidden treasures
That I now could mount!
How blind I had been
Not to have before these perls seen.

With Open Source software, the source code is open for you to use and modify.
FLOSS (Free/Libre/Open Source Software) is a term that covers both open source and free software. The author urges you to floss your PC!

LILO (LInux Loader), is a boot-loader that loads Linux for you. LILO has pretty much been replaced by GRUB (GRand Unified Boot-loader).
GNU stands for “GNU’s Not Unix”. Such acronyms are called recronyms.
gawk is a pattern-scanning tool.
mounting is how you access resources in Linux. You mount things, use them, and unmount them.
perl (Practical Extraction and Reporting Language) is a powerful scripting language that comes along with Linux.

It was as if
I was Bourne again.
No more rodent-fatigue that lingers
I have discovered use for my fingers!
etc.

bash (Bourne Again SHell) is a command-shell, the command-line prompt of which is where you enter commands. Oh yes, there used to be a Bourne shell too!

/etc is the directory where configuration details are usually stored.
***ROOT ALMIGHTY***

When I’m at the command line
Computer, obey the command mine.
For I am the Mandrake root,
I’ll slash all I want
Or backslash as is wont.
I might be mad as a Red Hatter
But in my kernel is a
A smouldering Caldera
Of raw, unbridled power.

Mandrake, Red Hat and Caldera are distributions of Linux.

root is the name of the super-user (user with administrative privileges) in Linux.
Mandrake-root is a narcotic/hallucinogen supposed to have magical powers. Indeed, Mandrake-root can make you mad as a hatter!
Slash (‘/’) and backslash(‘\’) are important keyboard characters for a command-line user.
The kernel is the heart of the operating system – that pumps life-blood into your PC, so to speak.
A caldera is a large crater at the top of a volcano.

I am Root Almighty,
God of the process-tree.
The world of demons, I am init.
Full control,
no holds barred.

To say that the root or super user is accorded God-status in Linux is by no means an exaggeration. If you are root, then you are all-powerful.

Processes are programs which are being run. Linux organizes the processes as a tree.
daemons are processes that operate in the background and provide services.
init is the very first process that is started when Linux boots. init starts the rest of the processes, including daemons.

I will tweak,
As is my custom,
till they squeak.

I wave the two-pronged fork
Children brought by the fabled stork
Ampersand when I kill
Become orphans or zombies.

Processes have a life of their own. forking is the method by which new processes are created, nay, born.
The new processes are called child-processes of the parent-process (what else!)
According to an old wives’ tale, storks bring children.
You can make any process run in the background by adding an ampersand (‘&’) when calling it. You can kill a process too. What is born must die! Orphans are child-processes whose parents have been killed and zombies are processes that are undead. Creepy?!

*** END OF ROOT ALMIGHTY***

Welcome to the free world!

Where you will no longer be told where to start.
Or commanded to issue the salute three-fingered
Even when it’s the OS that erred.
No longer be treated like minnows
Get to know more than that best Win knows.
No need for that software toss
Head or tail
More or less
I have made my choice.

The three-fingered salute is the dreaded Ctrl-Alt-Del key combination that one is forced to press in order to reboot a PC. Also called the `Vulcan nerve pinch’.

head is a program that shows the beginning of a file while tail shows the ending of a file.
more and less are programs that display a file one screen at a time. They are more or less the same. Except that less has more functionality!!! Yeah, you read that right.

If you have drunk the milk of the GNU
You will crave nothing Moo!

A gnu is also a large African antelope with a head resembling that of an ox.


- Thomas Jay Cubb

------------------------------------------------------------------------------------------------
CHANGE HISTORY

Version 1.2.0
1.Integrated man-pages inside the poem.
2.Added "floss!" line in poem
3.Changed and added some documentation
4.Moved "tweaking" para into "Root Almighty" section
5.Obfuscated proprietary-software bashing.

Version 1.1.0
1.Documentation "Punnix man-pages" added.
2.Line 3, Proprietary `propriety’ changed to Proprietary `property’
3.Line 5, ‘I wondered’ added
4.Line 17, Free ‘new’ world changed to Free ‘GNU’ world.
5.Line 22, how ‘stupid’ changed to how `blind’
6.Line 23, Not to have this before seen changed to ‘Not to have before these perls seen’
7.Line 24, `I’ changed to `It’ Had been a typo.
8.Couple of lines deleted (“I have…the key”)

Version 1.0.0
1.Initial version

------------------------------------------------------------------------------------------------

LICENSE

You may freely distribute copies of this post. But please retain this license message and do not modify the contents of the post. Please feel free to quote this in full or in part, anywhere you will. The author reserves the right to be identified as the creator of this poem and any part of it thereof. You can contribute to the evolution of this work by writing in with comments. Please do so!

-Thomas Jay Cubb,
Author

------------------------------------------------------------------------------------------------

Tuesday, September 06, 2005

C++ Name Origin

Rick Mascitti was the person who coined the term "C++". Before he did so, C++ was called C With Classes by Bjarne Stroustrup.

Some interesting quips can be found at
http://en.wikipedia.org/wiki/List_of_computer_term_etymologies#C and
http://en.wikipedia.org/wiki/C_Plus_Plus#History_of_the_name_.22C.2B.2B.22

I've also heard rumours that Java was called (likely in a lighter vein) "C++ --" !!
:-)

Monday, August 29, 2005

Copy-Paste and x-Handedness

The de facto key-combination for copy-pasting, the programmer's butter-knife, for most people is Ctrl-C (for Copy), Ctrl-V (for Paste). In fact, it is possible that you are conditioned to hear Ctrl-C, Ctrl-V as "Copy, Paste". This is the combination advertised on most Edit menus nowadays (along with Ctrl-X for Cut).

However, coming from a DOS/Unix shell background, I used to find it difficult to press Ctrl-C for Copy because it had negative connotations for me. It used to be (and still is) the keys to press to cancel a running command in a console.

FYI, the same things can be done using
Ctrl-Insert = Copy
Shift-Insert = Paste
Shift-Delete = Cut

I thought this made good sense.
Copy? okay, it's a control insert with no display-change.
Cut? shift into the buffer after deleting it from the display
Paste? Shift out the thing in the buffer and insert it here

Ergonomically, this is in fact better if you do a lot of selecting with the shift-cursor key combinations. You could do everything with your right hand.

So why should it have changed? In this age of GUIs, most people do their selecting with the mouse (with their right hand) and could do the copying/cutting and pasting with their left hand! Personally, I am against selecting stuff with the mouse coz it's more strenuous.

Why Ctrl-C,X,V then? Physical proximity is the only rationale, no logic as in the former case. C for Copy, so get the others nearby.

Or was it because "X" looks like a scissors and you use it to cut! So get the others nearby?

You wish!

Friday, August 26, 2005

Dream Word

This one is from my archives. Written in July 1997, this article is about what I felt (then) would have been cool features to have in a word-processor. Many have since been implemented and are standard features now. Many of the points are still valid though.

O, LORD PC! COULD I WRITE A LETTER ON YOU? . . . PLEASE!

Auto-Scroller tab

User keeps his mouse on the tab and the document keeps scrolling automatically. User can suspend by moving the mouse away or by pressing, say, Ctrl-V. It is very important to have an alternate key. Pressing another key, say PgUp or PgDn while in auto-scroller could bring another function.

Advanced OLE : Drag and select

User should be able to choose objects and text with a special drag. Maybe the concept of a right-button drag should be introduced.

Make-It-Fit!

Selected text or advanced OLE could be made to fit in a specified number of pages or a region created by special dragging.

Fonts

Super-scripting and sub-scripting should be available easily. Say by pressing a special key combination, say, Ctrl-Alt-F

Toolbars

Rather than themewise arrangement, a global toolbar with most universally and commonly used options should also be there. Themewise arrangement should also be there. Switching of toolbars must be simpler. Also, the program should keep a log of menu-items most used by the user and automatically place them on the toolbar.

Typo-Quikorrect!


Interchanging of letters to form words which do not exist can be easily identified. So why not correct it as well? But before correcting, program should go through the proper authorization channels. Flash it on the status bar whereupon the user can press a key to confirm. If the user does not press the key, he must be allowed to continue typing. No alarm-bells ringing! If the program is so particular that its message be heard, keep it in the error-bin, the user at the end of his session may or may not click the error-bin, a dialog box should open with various errors highlighted. User can then edit out unwanted corrections, press a confirmation key and lo, everything set right.

Equation format

All the word-processors can have a common format for scripting the equation. Type the numbers with codes, like, say, `^= for `raised to= etc. Drag it, block it and presto, encryption disappears and you have a well written equation on your hands. Neat! Wonder why it has not been implemented as of yet.

Menus

Arrangement of menu items should be more coherent and uniform. As far as possible, items common to all the word-processors must be grouped under menus with same or equivalent names.AUniformity by itself is no good.@ Jot it down! It=s a quote and what=s more, it is quotable! The logical arrangement of menu-items is a must-must.

WOFIWOG experience: Eh, what's that?

All in all, a WOFIWOG (What yOu Feel Is What yOu Get) experience is what all of us are searching for. Currently, what we are getting seems to be more of WIFIWYG.You guessed it right! Yes, a What I Feel Is What You Get experience, the I in the acronym standing for the PC and the You for you of course! (Who else? Did I really need to tell you that?) Got that Bill? Thank you!

Heron - Born Flightless?

The Heron Language is being developed by Christopher Diggins. Heavily influenced by C++. In search of a killer-app...
http://www.heron-language.com/

Some interesting concepts, but syntax seems to be somewhat cryptic with lots of `?' s in the code. The designer's site is at http://www.cdiggins.com/

Tuesday, August 09, 2005

Behaviour of typeid

code snippet to illustrate behaviour of typeid

struct
{
int side;
}square1;

struct
{
int side;
}square2;


int main(int argc, char *argv[])
{
if(typeid(square1)==typeid(square2))
printf("Same.");
else
printf("Different.");
}