Server Smalltalk Guide

Extensions to Kernel

The following classes that contain extensions to Kernel might be of use to you:

SstSharedQueue

Shared queues are synchronized queues, useful for passing objects between concurrent processes. They support standard queue protocol (add:, remove, and so on).

SstPool

Pools are a resource-management aid. A pool is configured with high and low watermarks and creation and destruction blocks. Objects ask a pool for one of its managed resources, and return the resource when finished. The pool creates and destroys resources as required. If set to strict the pool will strictly adhere to its configured watermarks, causing the request for the next available resource to return nil. Otherwise the pool allocates new resources as necessary, discarding surplus resources when returned. The creation block takes no arguments and should answer a resource; the destruction block takes a resource as an argument and should dispose of it.

SstPool conforms to the IuSstStartable interface and thus you must explictly start and stop it. Its operations are the following:

next
Answers a resouce. If no resources are available and the pool is strict, then answers nil.

return:
Returns a resource to the pool.

size
Answers the number of known resources.

SstWorkerManager

Worker-managers are similar to pools, but manage dispatching units of work. Managers maintain a list of worker processes for executing arbitrary blocks. A worker-manager has similar high and low watermarks, controlling the number of workers. If set to strict then blocks will be queued until a worker becomes available, otherwise a worker will be created as needed.

SstWorkerManager conforms to the IuSstStartable interface and thus you must explictly start and stop it. Its operations are the following:

dispatch:
Causes a block to be dispatched to a worker. If no workers are available, the block is queued to be executed when one becomes available.

workerName
Answers the name template given to worker processes.

workerName:
Sets the name template given to worker processes. A '%1' is replaced with the process' ID.

workerPriority
Answers the priority assigned to new worker processes.

workerPriority:
Sets the priority assigned to new worker processes.

SstRegistry and SstDualRegistry

Registries are a form of <keyedCollection>. Registries maintain dual mappings between a key and object, also known as a bijection: a key maps to one object, and each object is mapped to by only one key. Thus an object can be looked up to find its unique key. Registries also allow artibtrary objects to be "added", allocating new keys as necessary and preserving existing mappings for objects already added. SstDualRegistry are more efficient for situations requiring frequent key lookup given its object.

Registries are created giving a keyClass and objectClass, which should adhere to <keyedCollection>. The objectClass is used to map keys to their objects while the keyClass is used to map objects to their keys. The choice of these classes is very important to preserve the bijections maintained by the registry; the wrong choice of class will dramatically affect the behavior of the registry. These classes are usually either a LookupTable/Dictionary or an IdentityDictionary.

A rule of thumb for choosing the appropriate class is as follows: if the destination object (the object used as the value of the class) supports equivalence, then the class must be an IdentityDictionary. For example, if the keys of a registry are Symbols (which do not support equivalence) and the objects are Strings, then the keyClass must be an IdentityDictionary and the objectClass can be a LookupTable. Consider if the registry was asked to map 'foo' to foo and 'foo' copy to bar. Since String supports equivalence, then 'foo' and 'foo' copy will be equivalent. And if the keyClass (used to map the objects to their respective key) isn't identity-based, then 'foo' and 'foo' copy will map to same symbol and thus not preserving bijections. Thus, the keyClass must be an IdentityDictionary. But since Symbol does not support equivalence, the objectClass (mapping keys to their object) can be a LookupTable. If this confuses you, then a safe heuristic is: if both the keys and objects support equivalence, then use LookupTable. Otherwise use IdentityDictionary.

Registries mostly adhere to protocol and provides some additional protocol for determining reverse mappings.

SstDate

SstDate represents a moment in time, a combination of Smalltalk's Date and Time. SstDate supports a subset of Date and Time creation protocol, and most of their normal protocol.

SstDate has two possible representations. A relative date represents the time as a number of seconds since an epoch, an arbitrarily chosen fixed moment in time. As a result, only the local representation of the time changes with the local timezone, while the actual moment in time remains the same. For example, while 19:00 in Sydney may be 05:00 in Ottawa, it is only the local representation of the moment that is different: the actual moment in time is the same.

An absolute date, on the other hand, represents time in local time. Thus, 19:00 remains 19:00 even if the local timezone shifts to daylight savings. This is the traditional representation of Smalltalk's Date and Time.

A date can also be rooted to a particular timezone.

SstDate's printString gives the date in the standard internet format as defined by RFC1123.

There is protocol to determine whether a date is absolute or relative, and to answer a converted representation, and to answer the number of seconds/milliseconds from several popular epochs.

Because Smalltalk does not have any inherent concept of the local timezone, SST provides a workaround with the class method sstMinutesFromUTC: in Date. This method is given the number of minutes that the local timezone is from UTC; if ahead, the number should be positive, if behind UTC, then negative. The current offset can be queried with the class method sstMinutesFromUTC in Date. This mechanism does not adjust for daylight-savings and the like. If unset, then it is assumed that the system is in UTC.

SstCron

SstCron is a Smalltalk equivalent of Unix cron(1). SstCron allows automatic, repetitve scheduling of events, such as on the first of the month, or every Sunday, or every 5 seconds, or every 5 seconds when the first of the month is a Sunday. It also supports scheduling events to be run at a given moment such as 3:05 p.m. on Jan 1, 2004.

A cron entry (SstCronEntry) has a block (the unit of work), and a set of scheduling time constraints on months, days, days of the week, hours, minutes, and seconds, which are all relative to the local time zone. These constraints can have three possible types of values:

nil
The constraint is true for any possible value (the default).

collection
true for any values in the collection

integer
Shortcut for all multiples of the integer

An entry is considered ready-to-run when all of its constraints are met.

Entries are scheduled by adding a cron entry to the SstCron object (obtained with SstCron default) with add:, and stopped by removing the entry with remove:. Entries are automatically requeued to run at the next time satisfying its constraints. The entry is requeued only after it has finished executing. Thus an entry registered to execute every second taking takes five seconds to run will only be run every five seconds; there will not be multiple simulaneous executions.

It's easiest to show how to use SstCron with some examples:

"Primitive clock on the Transcript's title bar, updating every 5 seconds. 
Inspecting the entry will show %seconds was expanded to 
   (0 5 10 15 20 25 30 35 40 45 50 55) 
In Smalltalk terms this is (0 to: 59 by: 5). So specifying a single 
number really means: (minValue to: maxValue by: number)." 
SstCron default add: 
   (SstCronEntry new workBlock: [Transcript shell title: SstDate now printString];
   seconds: 5; 
   yourself)
"Run a backup every Sunday at midnight. Note that midnight (00:00:00) 
is regarded to be morning. Also note that it's important to specify the 
hours, minutes and seconds: otherwise they default to nil which means 
match every possible value. So without them explicitly specified you'd 
be running this event repeatedly all day! We don't set the month or day 
cause we want them to always match." 
SstCron default add: 
   (SstCronEntry new 
      workBlock: ["perform backup"]; 
      daysOfWeek: #(1); 
      hours: #(0); 
      minutes: #(0); 
      seconds: #(0); 
      yourself)
"Run this on the first Monday of the month. There can only be 
one day from the 1st to the 7th that's a Sunday." 
SstCron default add: 
   (SstCronEntry new 
      workBlock: [foo]; 
      days: (1 to: 7); 
      daysOfWeek: #(2); 
      hours: #(0); 
      minutes: #(0); 
      seconds: #(0); 
      yourself)
"This should be obvious"
SstCron default add: 
   (SstCronEntry at: (SstDate 
      newYear: 2000 
      monthIndex: 1 
      day: 1 
      hours: 0 
      minutes: 0 
      seconds: 0 
      milliseconds: 0) 
   do: [Transcript shell title: 'Happy New Year!'])


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]