I Use This!
Very Low Activity


Analyzed about 2 hours ago. based on code collected about 14 hours ago.
Posted almost 13 years ago by Holger Hans Peter Freyther
Intro The last couple of days, to some degree weeks I was implementing a SIP stack for GNU Smalltalk to be used in my Smalltalk GSM project. The first time I encountered SIP was around 2001 when we were excited to run a SIP Phone on our Linux powered ... [More] iPAQs (Linphone on Opie). For Smalltalk I started with looking at SipStack by Frank Shearar (who was very responsive to questions regarding his code and SIP in general). The main problem was that his stack was incomplete and as usual it is difficult to pick things up without knowing SIP and not knowing where the code was heading. Grammar I began with mapping the BNF SIP Grammar to rules for the PetitParser parsing framework. I have shortened some rules (e.g. because the generic rule is a catch-all one and I don't need the specialized form yet). Complexity The next big task was to deal with the concepts of a SIP Dialog, a SIP Session, a SIP Transaction and getting the relationship of these entities right. E.g. to place a call one creates an unconfirmed Dialog, prepares the INVITE Transaction and passes it to the transport layer. During this transaction one can get a reply that leads to a confirmation of the dialog. In fact one can end up with multiple confirmed dialogs (called forking, the target phones start ringing in multiple places and can be picked up multiple times as well). To make matters worse some answers need to be sent sent within the same transaction, some open a new one. My code seems to work now but there are some things I don't do properly (e.g. routing). I have documented this and if I have a need for those I will address them. Processes In the last couple of years I was mostly dealing with a single select IO model, coming to Smalltalk makes me use Processes to read and write from sockets. My basic model is to have a RX Process to use Socket>>#next and a TX process that will do SharedQueue>>#next and then Socket>>#nextPutAll. But with having multiple processes one is required to do proper locking, e.g. have a simple locking hierarchy (first pick the lock of the CallAgent, then the lock of a Dialog/Session). This all works nicely until I reached the point that I have two sub systems talking to each other. For setting up a call I might have one leg coming from GSM and use the MGCP Protocol, the other leg might be SIP. To hang-up I will need to inform the other leg of the call about it, but this means I will need to have a locking hierarchy that first takes all locks of the left leg of a call, then all locks of the right one which in turns means me I need to dispatch messages without any locks being held. Now besides having RX from maybe a couple of different Processes, I also deal with timeouts that will come from different Processes as well. Central dispatch To put an end to this (and the complications in the code) I created a simple queue that will BlockClosure>>#value a block from a central dispatch process, this way I have serialized everything and can mostly ignore locking. I hope that Smalltalk VMs will have a nice M:N Process model in the future and that my code will evolve into having different dispatchers running on these N native processes. Using the code st> PackageLoader fileInPackage: #OsmoSIP. st> transport :=SIPUdpTransport startOn: '' port: 5061. st> useragent := SIPUserAgent createOn: transport. st> transport start. "Starts the RX/TX process" st> call := SIPCall fromUser: 'sip:[email protected]' host: '' port: 5060 to: 'sip:[email protected]' on: useragent. st> call createCall: 'SomeSDP file'. st> call cancel. "E.g. before it is connected" st> call hangup. "E.g. when the call is connected." st> call terminate. "End the call somehow.." [Less]
Posted almost 13 years ago by Paolo Bonzini
Russ Cox of Plan-9 and Go fame posted a blog entry titled Floating Point to Decimal Conversion is Easy. While he is usually right, I believe this time he isn't. Floating point to decimal conversion is easy if you are okay with ugly results. A good ... [More] conversion routine will print the shortest decimal representation of the floating-point number, that is, the shortest decimal number whose closest floating-point representation equals the original number. You do not want 0.30000000001, you want 0.3, because the number right above 0.3 is 0.30000000003 and 0.30000000001 does not provide any extra precision. Otherwise, your users will complain. (And you need to make sure you got it right, otherwise they will complain even more). Here is how GNU Smalltalk does it. I'm pretty sure it is correct, too. Unlike the Go example in Russ Cox's article, GNU Smalltalk starts from an exact rational representation and relies on LargeIntegers. This is not a very efficient algorithm, but it is correct and optimal. Throughout the code, num will contain the error between the number to be printed (self, supposed positive) and the current partial representation (digits / weight; these variables are defined below. num := self asExactFraction. The algorithm tracks the decimal representation of two adjacent floating point numbers, num and the immediately successive number: "Smallest number such that self + eps ~= eps" eps := 2 raisedToInteger: self exponent - self class precision + 1. Note that eps is either an Integer, possibly large, or a Fraction. self exponent is the base-2 exponent of self, self class precision is the number of digits in the mantissa (53 for doubles). The initial approximation is, well, 0. But the denominator, weight is computed from the beginning to be close to self: digits := 0. exponent := num floorLog: 10. weight := 10 raisedToInteger: exponent. As we add digits to the approximation, the denominator will be reduced while remaining a power of 10. exponent and weight could be computed with a table or with binary search. We run the decimal conversion until we find a different digit in num versus each of num - eps and num + eps. Along the way, we remember whether we found a digit that is not 9: allNines := true. sameDown := true. sameUp := true. [digit := num // weight. allNines := allNines and: [digit = 9]. sameDown := sameDown and: [(num - eps) // weight = digit]. sameUp := sameUp and: [(num + eps) // weight = digit]. num := num - (digit * weight). prevWeight := weight. weight := weight / 10. sameDown or: [sameUp]] whileTrue. Now we have a correct approximation, but perhaps not an optimal one. For simplicity, I'll accept a possible unoptimality in case of floating-point numbers that are integer and so big that num+0.5 cannot be represented exactly: eps isInteger ifTrue: [eps := eps / 2]. Without this line, round-to-even behavior of the decimal-to-binary conversion may cause bugs. At this point num is the error that remains in the decimal representation. So, the error by tweaking the lowest significant digits in the decimal representation will be something like num - (NN * prevWeight) and num + (NN * prevWeight), respectively if you add or subtract NN from the lowest significant digit in the decimal representations. adjust will contain what I wrote above as NN: adjust := 0. The first improvement is to try rounding the last digit while not changing the meaning. Try rounding down: (digit <= 5 and: [num + (digit * prevWeight) < (eps / 2)]) ifTrue: [adjust := digit negated]. so that e.g. 0.30000000001 will set adjust to -1 ("subtract 1", giving 0.3); and then up: (digit > 5 and: [num + ((digit - 10) * prevWeight) > (eps / -2)]) ifTrue: [adjust := 10 - digit]. In this case 0.8999999996 will set adjust to 4 ("add 4", giving 0.9). The second improvement is only done if the above didn't trigger. It tries adding 1, and see if that moves us closer to self. This is needed because digits are always found with //, which truncates the result rather than rounding it: (adjust = 0 and: [digit > 0]) ifTrue: [ (num - prevWeight) abs < num ifTrue: [adjust := 1]]. The tweak is also skipped if the last digit is 0. In this case, the decimal representation we have may make the representation more precise but it would also make the result longer. Now we can perform the adjustment (but be careful about moving the decimal point, if necessary, when rounding up!): digits := digits + adjust. (adjust > 0 and: [allNines]) ifTrue: [allNines := false. exponent := exponent + 1]. Now we have converted self asExactFraction (a fraction from one whose denominator is a power of 2) to another fraction, whose denominator is a power of 10. digits is the numerator of this new fraction, while the denominator is 10exponent. Let's convert the numerator to a string in order to print it: digits := digits printString. Keep the significant digits only, we convert it to a stream for easy iteration: precision := digits findLast: [:ch | ch ~= $0]. digitStream := ReadStream on: digits from: 1 to: precision. GNU Smalltalk now chooses whether to print in exponential notation or not. For simplicity I will cover the exponential notation case only. The destination stream at last comes into play; it's called aStream. Remember that we stripped all zeros above, so we'll handle it specially. First print the first character, which is the integer part: digitStream atEnd ifTrue: [aStream nextPut: $0]. ifFalse: [aStream nextPut: digitStream next]. Then the decimal point and everything else: aStream nextPut: $.. digitStream atEnd ifTrue: [aStream nextPut: $0] ifFalse: [aStream nextPutAll: digitStream]. and finally the exponent letter: aStream nextPut: $e; print: exponent That's it. It is not incredibly complex, but also not too optimized and full of off-by-one traps. So, good floating point to decimal conversion is not so easy! [Less]
Posted about 13 years ago by Mathieu Suen
The previous post I have show you an example on how to create a simple windows using the objective-c binding. Still it was working it was not so flexible. If you fetch the latest commit from github you will have enhancement quoted below: Direct ... [More] access to ObjC class Unary method pragma for method override Super send Bug fix Note the the binding can run on OSX and use gnustep for other platform. See my previous post for installation details 1. Direct access to ObjC class Thanks to gnu-smalltalk namespace, Objective-c class can now be access directly from Objc. newWindow = Objc.NSWindow alloc. 2. Unary method pragma for method override When subclassing a objective-c class it was require that you add the type encoding of the method. Now if you know that the method you are adding is in the superclass the binding will find the type encoding for you. For example if you override the -drawRect: method of NSView you can simply do: Objc.ObjcObject subclass: MyNSView [ &ltobjcSubclass: 'NSView'&gt drawRect: rect [ &ltobjc&gt Objc.NSColor redColor set. Objc.ObjcAppKit nsRectFill: self bounds ] ] Note that for this feature you will need to fetch the latest gst from my repository or wait for the patch. This is because unary pragma are currently not supported in gst. 3. Super send In a method that you override you can now do a super send. This is particularly useful when overriding -init init [ &ltobjc&gt super init ] Super send to objective-c object will only forward the lookup to the ObjC runtime if the class where the super send is written is a direct subclass of Objc.ObjcObject That is it for the time being. Fell free to comment or ask me questions. Many thanks to David Chisnall who helps me a lot to get the type encoding right. [Less]
Posted about 13 years ago by Mathieu Suen
Recently I have done some work on the gst-objective-c-binding. Now most of the basic feature is here. Of course a lot of polishing still need to be done. The binding now support sending message from objective-c to smalltalk and from smalltalk to ... [More] objective-c. You can also sublcass some objective-c class like NSView. In this post I will show you how to get the bridge working and create you first Cocoa app. Getting gst-objc (If you have a better name idea feel free to give me suggestions.) You can fetch the source from github: $ git clone git://github.com/mathk/gst-objc.git Then you have to build it. $ autoreconf -vi $ ./configure $ make $ [sudo] make install Depending on you platform you may need gnustep. You can find all the instruction to build gnustep here. Here you should be able to load Objc package: GNU Smalltalk ready st> PackageLoader fileInPackage: 'Objc' Loading package Objc 2011-05-01 22:17:52.971 gst[91826:903] Load complete PackageLoader st> First window Now that you can load Objc I will show you how to create a NSWindows. For convenience I will drop every thing in a file myFirstWindow.st "First load the package" Eval [ PackageLoader fileInPackage: 'Objc'. ] After that we need to create a NSApplication that will handle the main event loop. nsApplication := Objc.ObjcRuntime at: 'NSApplication'. nsApp := nsApplication sharedApplication. As you can see when sending #sharedApplication to the object your are in fact forwarding the message to objective-c. We can then create our first NSWindows: nsRect := Objc.NSRect gcOriginX: 0.0 y: 0.0 width: 100.0 height: 100.0. nsWindow := Objc.ObjcRuntime at: 'NSWindow'. nsWindow := nsWindow alloc. nsWindow initWithContentRect: nsRect styleMask: 15 backing:Objc.ObjcAppKit nsBackingStoreBuffered defer: (Character value:1). nsWindow setTitle: 'Test windows' asNSString. nsRect is just a CStruct that tell which size the window is going to have. #initWithContentRect:styleMask:backing:defer: and #setTitle: are again forwarded to objective-c. You have to be careful to chose the right type when passing argument to objective-c. For instance the last parameter is of type 'c' in objective-c which is a Character. #asNSString is a helper to convert from smalltalk string to objective-c string like @"Testing window". After that we have to create a NSView. The way NSWindow handle the drawing is by calling #drawRect: on a view. So we have to subclass NSView and implement the #drawRect: method. The way to do this is by using class and method pragma. Objc.ObjcObject subclass: MyNSView [ <objcSubclass: 'NSView'> drawRect: rect [ "if you are running on gnustep you have to use: v@:{_NSRect={_NSPoint=dd}{_NSSize=dd}} and use f or d depending on you arch 32 or 64bit. This need to be improve. " <objcTypeStr:'v@:{CGRect={CGPoint=dd}{CGSize=dd}}'> | nsColor | nsColor := Objc.ObjcRuntime at: 'NSColor'. nsColor redColor set. Objc.ObjcAppKit nsRectFill: self bounds ] ] The pragma objcSubclass: tells what is the super class. In oder word MyNSView is a subclass of NSView. The pragma objcTypeStr: tells the type of the objective-c method. You can found out more here. The #drawRect: method is pretty simple. It just fill the window in red. Now we can use this newly create class: "Create a new view but don't retain it. Instead autorelease it." view := MyNSView noRetainAlloc. view init. view autorelease. nsWindow setContentView: view. nsWindow center. nsWindow orderFront: 0. nsWindow contentView. nsApp run. At this point you should see a small window fill of red. That is it for this tutorial. I hope you enjoy it. Fell free to ask questions or comments. Last I would like to thanks Paolo Bonzini and David Chisnall for theirs helps and advices. Complete code: Eval [ PackageLoader fileInPackage: 'Objc'. ] Objc.ObjcObject subclass: MyNSView [ drawRect: rect [ | nsColor | nsColor := Objc.ObjcRuntime at: 'NSColor'. nsColor redColor set. Objc.ObjcAppKit nsRectFill: self bounds ] ] Eval [ | nsClass nsInstance nsApplication nsApplicationClass nsBundle nsApp nsAuto object | nsApplication := Objc.ObjcRuntime at: 'NSApplication'. nsApp := nsApplication sharedApplication. nsRect := Objc.NSRect gcOriginX: 0.0 y: 0.0 width: 100.0 height: 100.0. nsWindow := Objc.ObjcRuntime at: 'NSWindow'. nsWindow := nsWindow alloc. nsWindow initWithContentRect: nsRect styleMask: 15 backing:Objc.ObjcAppKit nsBackingStoreBuffered defer: (Character value:1). nsWindow setTitle: 'Test windows' asNSString. view := MyNSView noRetainAlloc. view init. view autorelease. nsWindow setContentView: view. nsWindow center. nsWindow orderFront: 0. nsWindow contentView. nsApp run. ] [Less]
Posted about 13 years ago by Gwenael Casaccio
Hi, In this little tutorial we will build a simple UI. The counter tutorial is just a window with two buttons and a label; we will see how to add widgets in the main window and how to handle the Gtk events. The Model First create a counter class ... [More] , with an instance variable counter, a method which sets the initial value of the counter, an incrementor and decrementor methods with an converstion method that convert the counter as a string. " Counter class " Object subclass: Counter [ | counter | counter: anInteger [ " setter " counter := anInteger ] counterString [ " return the counter value as a string " ^ counter asString ] increment [ " increment the counter and signal that the value as changed " counter := counter + 1. self changed: #counterString ] decrement [ " decrement the counter and signal that the value as changed " counter := counter - 1. self changed: #counterString ] ] The User Interface Now we will create the application window and the differents widgets inside it: | b1 b2 counter label frame window | " The window " window := GtkTools GtkMainWindow new. " The counter with an initial value set to 0 " counter := Counter new counter: 0; yourself. " The layout where widgets will be displayed " frame := GTK GtkFixed new. " A new button " b1 := GTK GtkButton labeled: '+'. " Send the increment message to counter when the user click on the button " b1 onClick: #increment to: counter. " Add the button to the frame " frame at: 50@20 put: b1. " A new button " b2 := GTK GtkButton labeled: '-'. " Send the decrement message to counter when the user click on the button " b2 onClick: #decrement to: counter. " Add the button to the frame " frame at: 50@80 put: b2. " The label " label := GTK GtkLabel new: '0'. " Update the label when counter update its value " label refreshFrom: #counterString for: counter. frame at: 190@58 put: label. window centralWidget: frame; title: 'simple'; statusMessage: 'Simple GTK Application'; " Set the application size " resize: 230@150; " Set the application icon " icon: (GTK.GdkPixbuf fromFile: 'visualgst.png'); showAll. counter increment. GTK Gtk main [Less]
Posted about 13 years ago by Gwenael Casaccio
Hi, In this short tutorial I will explain how to create a simple GTK application with GNU Smalltalk. First of all we download the gtk-tools package which contains improvements for Gtk. git clone [email protected]:gst-objectspaces/gtk-tools.git cd ... [More] gtk-tools ./package.sh Now we can create a first Gtk application; first we load the gtk-tools package " Create a temporary variable " | window | PackageLoader fileInPackage: 'GtkTools'. " This is a simple program that creates a window with a button and a status bar: " " Create a new window " window := GtkTools GtkMainWindow new. " Set a button as the main widget, change the title and status bar " window centralWidget: (GTK.GtkButton labeled: 'Hello World'); title: 'simple'; statusMessage: 'GTK Tutorial'; showAll. " Display me and my children " " Launch the Gtk event loop " GTK.Gtk main. Here is the result: As you can see it is really easy to create a simple toy application with Gtk and GNU Smalltalk. In the next episode we will see how to do a simple counter application ;-) [Less]
Posted about 13 years ago by Canol Gökel
Welcome to GNU Smalltalk (GST) monthly digest, a place to find a summary of happenings from the world of GST. If you don't know what GST is, you can look at [1] to learn more about this beautiful programming language. Here are some of the news ... [More] happened last month: Nicolas Petton announced Jtalk. Jtalk is an implementation of the Smalltalk language that runs on top of the JavaScript runtime: http://forum.world.st/Jtalk-a-Smalltalk-for-web-developers-td3354669.htm... Gwenael Casaccio is now a part of Planet GNOME: http://smalltalk.gnu.org/blog/mrgwen/hello-planet-gnome GNU Smalltalk 3.2.4 released: http://smalltalk.gnu.org/blog/mrgwen/gnu-smalltalk-3-2-4 GNU Smalltalk 4.1 is also released: http://forum.world.st/GNU-Smalltalk-4-1-released-td3419830.html Mathieu Suen explains how to use MiniDebugger, a command line debugger for GST: http://smalltalk.gnu.org/blog/mathk/how-use-minideubgger The WebQA did an interview with Nicolas Petton: http://www.thewebqa.com/javascript/nicolas-petton-on-smalltalk-on-the-ja... Chasing memory leaks: http://forum.world.st/Strategy-to-finding-memleaks-td3438067.html [1] GNU Smalltalk is a free implementation of the Smalltalk-80 programming language. It runs on most POSIX compatible operating systems (including GNU/Linux, of course), as well as under Windows. Smalltalk is a dynamic, purely object-oriented programming language, also well-versed in scripting tasks. You can get more information from: http://smalltalk.gnu.org/ Mailing list: http://smalltalk.gnu.org/community/ml http://forum.world.st/Gnu-f1290346.html Blogs: http://smalltalk.gnu.org/blog Wiki: http://smalltalk.gnu.org/wiki [Less]
Posted about 13 years ago by Holger Hans Peter Freyther
For the SS7/GSM work I am doing I have to implement dialogues with other systems and by default the IO in a lightweight process in Smalltalk is blocking (built on top of SIGIO). My problem is that a remote system could make me wait for a response ... [More] forever. I am not an experienced Smalltalker yet but the existing options didn't look good enough (which might be me being unexperienced). I looked into what is required to add a #timeout:do: to the BlockClosure. The idea is to run the dialogue in a very straight forward way and guard the whole operation with a Timeout. [ self sendSomething. self waitForResponseOfKind: ABC. self someMoreStuff. self waitForMoe. self askOtherSystem. self conclude. ] timeout: 10 do: ['The operation timed out... cleanup'] It turned out to be quite easy to do in GNU Smalltalk. The BlockClosure extension creates a new Process which uses the Delay class to wait for the delay. The new delay process holds on to the BlockClosure and has a Semaphore. If the normal evaluation exists the Semaphore signals in case the timeout occurs before the original Process queues an interrupt that sends a TimeoutNotification. Is there a better way to achieve such patterns? [Less]
Posted about 13 years ago by Canol Gökel
The WebQA did an interview with Nicolas Petton, co-author/author of Iliad Web Framework and Jtalk. You can find the interview here: http://www.thewebqa.com/javascript/nicolas-petton-on-smalltalk-on-the-ja...
Posted about 13 years ago by Mathieu Suen
First you need to load MiniDebugger in your image. gst -K examples/MiniDebugger.st -S You may have to sudo it. su -c 'gst -K examples/MiniDebugger.st -S' This will save the image with MiniDebugger loaded. Next time you encounter a exception the ... [More] MiniDebugger will prompt. You can type help for more info: [mathk@mathk examples]$ gst GNU Smalltalk ready st> self halt 'nil error: halt encountered' Halt(Exception)>>signal (ExcHandling.st:254) Halt(Exception)>>signal: (ExcHandling.st:264) UndefinedObject(Object)>>halt: (SysExcept.st:1423) UndefinedObject(Object)>>halt (Object.st:1325) UndefinedObject>>executeStatements (a String:1) 6 ^self activateHandler: (onDoBlock isNil and: [ self isResumable ]) (debug) help Control flow commands: s [n] step N times n [n] next (step over send) N times f [n] finish current method N times c continue Process commands: no ID means debugged process P show process list T [id]... terminate process K [id]... kill process - no unwinds or cleanup b [id]... backtrace Examining state: r print receiver on stdout i inspect (enter MiniInspector on current receiver) I inspect context (enter MiniInspector on current context) e eval (enter read-eval-print loop on current receiver) Examining the call stack: u [n] go N frames up (default 1) d [n] go N frames down (default 1) l print current method w print current frame Other commands: g collect all garbage X exit Smalltalk, and dump core x exit Smalltalk (debug) [Less]