A standalone VR headset is a headset that can work without being tethered to a computer. Tethered headsets (Oculus, HTC Vive, PSVR, Windows Mixed Reality headsets) needs to be connected to a computer/game-console to function. ... However due to mobility, standalone headsets are less powerful.
There are currently nowhere near as many untethered VR headsets available in the burgeoning virtual reality market, compared to PC VR (tethered VR) and smartphone VR.
Tethered VR/AR HMDs must be connected by cable to a PC, harnessing the powerful processing power of the hardware in the connected PC or console. However, mobile VR headsets use the more widely accessible and available smartphones to deliver less advanced VR.
Standalone virtual reality headsets (a.k.a. untethered, wireless, standalone VR) don't require a PC or a smartphone to deliver a VR experience. The self-contained headsets (made popular by releases such as the Oculus Go) include built-in processors, GPU, sensors, battery, memory, displays, and more. In addition, as these VR goggles are uncabled, users don't have to limit themselves to a restricted space. In general, they offer a more powerful VR experience than smartphone VR but less powerful than tethered VR.
DPVR (or Deepoon) has a few VR products available, however, this is the only standalone VR headset available from the manufacturer. One of the features is the ability to relatively quickly recharge the VR HMD. Although it has a high price-point, it doesn't offer the same high specs as other all-in-one headsets available. Furthermore, no controllers are available.
Pros:
Low latency
Quick battery recharge
Cons:
No controllers
Less affordable than most products in this VR category
This untethered VR was one of the first HMDs in the category to be released, and it has good specs considering. With 110 degrees FOV, a decent refresh rate of 75Hz and the standalone VR is compatible with a variety of OS. However, due to the age of the device, it is the least future-proofed and user feedback was negative on the comfort and content available.
Pros:
Affordable price-point
Runs on multiple OS
Cons:
Dated technology
Poor comfort and wearability
Bad ventilation and can overheat
The VIVE FOCUS is one of the few standalone VR headsets to have 6DoF (6 Degrees of Freedom), hence the much higher price-point. However, this HMD does offer a range of features such as additional 2TB storage, basic gesture tracking, and longer battery life compared to other devices in this category.
Pros:
Built-in microphone and speakers
Ongoing software updates for improvements
6DoF
Cons:
High price-point
This standalone VR headset is not as affordable as other options on our list, but it has better specs compared to some of the other HMDs available. The Mirage Solo offers a more immersive VR experience than other VR headsets lacking 6DoF. On the downside is the heavy, large design making is less portable for users.
Pros:
Great storage and memory options
High accuracy of positional tracking
Long battery life
Cons:
Bulky design, heavy and uncomfortable to wear & not ideal for portability
Lacks built-in speakers
A shortfall in great content
The Oculus Go is arguably the most well-known example of standalone VR, therefore it is credited with increasing the visibility of VR in the mass market. The HMD is very easy to use and the plug and play setup caters for beginners and experienced users. The Oculus Go provides accessible VR of very good quality at this price-point.
Pros:
Affordable all-in-one VR
Comfortable design and fit
Large range of content available
Cons:
Only 3DoF
Basic controller
Long recharge time
This video showcases a review of one of the most popular mobile VR headset offerings, the Oculus Go


About
Information about the HCW-HOSTED initiative
Mission
Provide temporary housing to the healthcare workforce throughout the COVID-19 pandemic surge & offer physical, psychosocial support, and protection to their families and community
Vision
To stop the COVID-19 pandemic as quickly and humanely as possible
Who we are
The founding consortium for HCW HOSTED is a multi-disciplinary partnership between the University of Arizona (UA), local hospital systems, the Tucson business community, city and county government officials, and concerned citizens.
The consortium’s leadership team at UA consists of emergency room physicians, public health specialists, epidemiologists, public health emergency management specialist, clinical psychologists with teletherapy resources and psychological first aid experience, data scientists, and web developers who are supported by over 30 faculty, staff, and students motivated to launch this initiative immediately to support frontline personnel through the COVID-19 pandemic surge.
Catalytic Team
Mona Arora, Principal Research Specialist & Course instructor - MEZCOPH, University of Arizona
Amy Athey, Executive Director, Student Wellness and Retention, University of Arizona
Charles Brands, Graduate Student, Public Health, MBA, University of Arizona
Stephen Crabbe, Graduate Student, Emergency Medicine, Public Health, University of Arizona
Collin Catalfamo, Doctoral Student, Epidemiology, MEZCOPH, University of Arizona
Bradley Dreifuss, MD FACEP, Emergency Medicine Physician and Assistant Professor of Emergency Medicine and Public Health, University of Arizona
Heather Dreifuss, MEZCOPH DPH Candidate, University of Arizona
Kate Ellingson, Assistant Prof of Public Health, Infectious Dz Epi - MEZCOPH, University of Arizona
Azad Molla Hosseini, Graduate Student, Emergency Medicine, Law, University of Arizona
Sana Khan, Doctoral Student, Epidemiology, MEZCOPH, University of Arizona
Claudia Kelly, Logistics Coordinator, Strategist
Beth Jacobs, MEZCOPH/UA Cancer Ctr Professor of Epidemiology and Biostats, University of Arizona
Nirav Merchant, Director, Data Science Institute, University of Arizona
Mark Nichter, Regents' Professor and Professor of Anthropology, Public Health, Family Medicine, University of Arizona
Brittany Nigon, MPH, Outreach Coordinator, Arizona AIDS Education & Training Center/ Petersen HIV Clinics, College of Medicine, University of Arizona
Mary-Frances O'Connor, Professor of Psychology; Director of Training in Pscyhology, University of Arizona
Mark Sundman, Doctoral Candidate, College of Psychology, University of Arizona
Alison Sutton-Ryan, Director of Mental Health Services for GME & UME, University of Arizona
Tyson Lee Swetnam, Assistant Research Professor, CyVerse, BIO5 Institute, University of Arizona
Web Development
Devin Bayly, Research Computer Scientist, University of Arizona
Alex Bigelow, Postdoctoral Researcher, Data Science Fellow, CyVerse, Computer Sciences, University of Arizona
Aiden Fishbein, Hackathon participant
Blake Joyce, Assistant Director, Research Computing, University of Arizona
Sophie Sheeline, Hackathon participant, Mechanical Engineer, FRESH Health
Jordan Thompson, Software Engineer, CyVerse, BIO5 Institute, University of Arizona
Mariah Wall, Graphic Artist, CyVerse, BIO5 Institute, University of Arizona


| Package | Description |
|---|---|
| javax.rmi.CORBA |
Contains portability APIs for RMI-IIOP.
|
| org.omg.CORBA |
Provides the mapping of the OMG CORBA APIs to the JavaTM
programming language, including the class ORB, which is implemented
so that a programmer can use it as a fully-functional Object Request Broker
(ORB).
|
| org.omg.CORBA.DynAnyPackage |
Provides the exceptions used with the
DynAny interface
(InvalidValue ,
Invalid , InvalidSeq , and
TypeMismatch ). |
| org.omg.CORBA.ORBPackage |
Provides the exception
InvalidName , which is thrown
by the method ORB.resolve_initial_references
and the exception InconsistentTypeCode , which is thrown
by the Dynamic Any creation methods in the ORB class. |
| org.omg.CORBA.TypeCodePackage |
Provides the user-defined exceptions
BadKind
and Bounds , which are thrown by methods in
in the class TypeCode . |
| org.omg.CORBA.portable |
Provides a portability layer, that is, a set of ORB APIs
that makes it possible for code generated
by one vendor to run on another vendor's ORB.
|
| org.omg.CORBA_2_3 |
The CORBA_2_3 package defines additions to existing CORBA interfaces
in the Java[tm] Standard Edition 6. These changes occurred in recent
revisions to the CORBA API defined by the OMG. The new methods were
added to interfaces derived from the corresponding interfaces in
the CORBA package. This provides backward compatibility and avoids
breaking the JCK tests.
|
| org.omg.CORBA_2_3.portable |
Provides methods for the input and output of value types, and contains
other updates to the
org/omg/CORBA/portable package. |
| org.omg.CosNaming |
Provides a naming service for Java IDL.
|
| org.omg.CosNaming.NamingContextExtPackage |
This package contains the following classes, which are used in
org.omg.CosNaming.NamingContextExt:
|
| org.omg.CosNaming.NamingContextPackage |
This package contains Exception classes for the org.omg.CosNaming
package.
|
| org.omg.Dynamic |
This package contains the Dynamic module specified in the OMG Portable
Interceptor specification,
http://cgi.omg.org/cgi-bin/doc?ptc/2000-08-06, section 21.9.
|
| org.omg.DynamicAny |
Provides classes and interfaces that enable traversal of the data value
associated with an
any at
runtime, and extraction of the primitive constituents of the data value. |
| org.omg.DynamicAny.DynAnyFactoryPackage |
This package contains classes and exceptions from the DynAnyFactory
interface of the
DynamicAny module
specified in the OMG The Common Object Request Broker: Architecture and
Specification,
http://cgi.omg.org/cgi-bin/doc?formal/99-10-07, section 9.2.2.
|
| org.omg.DynamicAny.DynAnyPackage |
This package contains classes and exceptions from the DynAny
interface of the DynamicAny module
specified in the OMG The Common Object Request Broker: Architecture and
Specification,
http://cgi.omg.org/cgi-bin/doc?formal/99-10-07, section 9.2.
|
| org.omg.IOP |
This package contains the IOP module specified in the OMG document
The Common
Object Request Broker: Architecture and Specification,
http://cgi.omg.org/cgi-bin/doc?formal/99-10-07, section 13.6.
|
| org.omg.IOP.CodecFactoryPackage |
This package contains the exceptions
specified in the IOP::CodeFactory interface (as part of the Portable
Interceptors spec).
|
| org.omg.IOP.CodecPackage |
This package is generated from the IOP::Codec IDL interface
definition.
|
| org.omg.Messaging |
This package contains the Messaging module specified in the OMG CORBA
Messaging specification,
http://cgi.omg.org/cgi-bin/doc?formal/99-10-07.
|
| org.omg.PortableInterceptor |
Provides a mechanism to register ORB hooks through which ORB services
can intercept the normal flow of execution of the ORB.
|
| org.omg.PortableInterceptor.ORBInitInfoPackage |
This package contains the exceptions and typedefs from the ORBInitInfo
local interface of the PortableInterceptor module specified in the OMG
Portable Interceptor specification,
http://cgi.omg.org/cgi-bin/doc?ptc/2000-08-06, section 21.7.2.
|
| org.omg.PortableServer |
Provides classes and interfaces for making the server side of your applications
portable across multivendor ORBs.
|
| org.omg.PortableServer.CurrentPackage |
Provides method implementations with
access to the identity of the object on which the
method was invoked.
|
| org.omg.PortableServer.POAManagerPackage |
Encapsulates the processing
state of the POAs it is associated with.
|
| org.omg.PortableServer.POAPackage |
Allows programmers to construct object implementations that are portable
between different ORB products.
|
| org.omg.PortableServer.ServantLocatorPackage |
Provides classes and interfaces for locating the servant.
|
| org.omg.SendingContext |
Provides support for the marshalling of value types.
|
| org.omg.stub.java.rmi |
Contains RMI-IIOP Stubs for the Remote types that occur in the
java.rmi package.
|
| Class and Description |
|---|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| InvokeHandler
This interface provides a dispatching mechanism for an incoming call.
|
| ObjectImpl
The common base class for all stub classes; provides default implementations
of the
org.omg.CORBA.Object methods. |
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| ApplicationException
This class is used for reporting application level exceptions between ORBs and stubs.
|
| BoxedValueHelper |
| Delegate
Specifies a portable API for ORB-vendor-specific
implementation of the org.omg.CORBA.Object methods.
|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| ObjectImpl
The common base class for all stub classes; provides default implementations
of the
org.omg.CORBA.Object methods. |
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| RemarshalException
This class is used for reporting locate forward exceptions and object forward
GIOP messages back to the ORB.
|
| ServantObject
This class is part of the local stub API, the purpose of which is to provide
high performance calls for collocated clients and servers
(i.e.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| ValueBase
The generated Java classes corresponding to valuetype IDL types
implement this interface.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| Class and Description |
|---|
| ApplicationException
This class is used for reporting application level exceptions between ORBs and stubs.
|
| Delegate
Specifies a portable API for ORB-vendor-specific
implementation of the org.omg.CORBA.Object methods.
|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| RemarshalException
This class is used for reporting locate forward exceptions and object forward
GIOP messages back to the ORB.
|
| ResponseHandler
This interface is supplied by an ORB to a servant at invocation time and allows
the servant to later retrieve an OutputStream for returning the invocation results.
|
| ServantObject
This class is part of the local stub API, the purpose of which is to provide
high performance calls for collocated clients and servers
(i.e.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| ValueBase
The generated Java classes corresponding to valuetype IDL types
implement this interface.
|
| Class and Description |
|---|
| ValueFactory
The ValueFactory interface is the native mapping for the IDL
type CORBA::ValueFactory.
|
| Class and Description |
|---|
| BoxedValueHelper |
| Delegate
Specifies a portable API for ORB-vendor-specific
implementation of the org.omg.CORBA.Object methods.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| ObjectImpl
The common base class for all stub classes; provides default implementations
of the
org.omg.CORBA.Object methods. |
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| InvokeHandler
This interface provides a dispatching mechanism for an incoming call.
|
| ObjectImpl
The common base class for all stub classes; provides default implementations
of the
org.omg.CORBA.Object methods. |
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| ResponseHandler
This interface is supplied by an ORB to a servant at invocation time and allows
the servant to later retrieve an OutputStream for returning the invocation results.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| ObjectImpl
The common base class for all stub classes; provides default implementations
of the
org.omg.CORBA.Object methods. |
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| ValueBase
The generated Java classes corresponding to valuetype IDL types
implement this interface.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| InvokeHandler
This interface provides a dispatching mechanism for an incoming call.
|
| ObjectImpl
The common base class for all stub classes; provides default implementations
of the
org.omg.CORBA.Object methods. |
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| ResponseHandler
This interface is supplied by an ORB to a servant at invocation time and allows
the servant to later retrieve an OutputStream for returning the invocation results.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Class and Description |
|---|
| InputStream
InputStream is the Java API for reading IDL types
from CDR marshal streams.
|
| OutputStream
OuputStream is the Java API for writing IDL types
to CDR marshal streams.
|
| Streamable
The base class for the Holder classess of all complex
IDL types.
|
| Class and Description |
|---|
| IDLEntity
An interface with no members whose only purpose is to serve as a marker
indicating that an implementing class is a
Java value type from IDL that has a corresponding Helper class.
|
| Class and Description |
|---|
| ObjectImpl
The common base class for all stub classes; provides default implementations
of the
org.omg.CORBA.Object methods. |
Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2015, Oracle and/or its affiliates. All rights reserved.


{% if messages %}
{% for message in messages %}
You have requested a class that doesn't exist in PaleoCore yet.
{{ message }}
{% endfor %} {% endif %} {% if not matching_class %}You have requested a class that doesn't exist in PaleoCore yet.
{% else %}
{% if matching_terms %}
Terms in the '{{ matching_class.name }}' class.
Term
Definition
{% for term in matching_terms %}
{{ term.name }}
{{ term.definition }}
{% endfor %}
{% else %}
There are no '{{ matching_class.name }}' terms in PaleoCore yet.
{% endif %}
+ Add New Term
Join the Discussion about the '{{ matching_class.name }}' class.
comments powered by Disqus
{% endif %}
Terms in the '{{ matching_class.name }}' class.
| Term | Definition |
| {{ term.name }} | {{ term.definition }} |


Consistency Is Your Friend
Note: None of the following is set in stone. This is merely a way to start discussion on some issues with syntactic inconsistencies in Corinna.
Years ago I was working with some graphing software where points would be declared via:
var point = point(2,3);
Except that the point
function took Y,X
as arguments, not the near
universally-accepted X,Y
. To this day, I loathe the author of that library
for making my life hell.
On a more personal note, while building Tau Station —a narrative sci-fi MMORPG—I was trying to respect proper separation of concerns and not building god objects, so when it came time to check if an NPC has a mission for a character, I had this:
if ( $missions->has_mission_for( $character, $npc ) ) {
...
}
Or was it this?
if ( $missions->has_mission_for( $npc, $character ) ) {
...
}
To this day, I cannot remember which style I used and what justification I had
for that, but it was a constant source of bugs because I kept getting the
$npc
and $character
swapped. So I bit the bullet and decided that, as much
as possible, Tau Station code would follow SVO (subject-verb-object) syntax,
instead of the weird “context-verb-subject-object” I had created. Or was it
“context-verb-object-subject”? Who knows? Instead, the above became this:
if ( $npc->has_missions_for($character) ) {
...
}
And now the meaning of the code is crystal clear, though people will complain about “God objects” (which I address here ).
Consistency brings clarity. Reasoning about code is hard enough when it appears to be an ad-hoc mishmash of rules.
So, um, that brings us to the Corinna project , my attempt to bring modern object-oriented programming to the Perl language.
Language Design
As I’ve previously pointed out, my first foray into language design didn’t go as well as I hoped. At its heart, you can think of language design as consisting of three parts:
- Semantics
- Syntax
- Community
I mostly had the semantics and syntax down, but I hadn’t done a great job of paying attention to the community. The community feedback was mixed, to put it politely. So an IRC channel was created (irc.perl.org #cor) and a github project was started and anyone with an interest in the project was welcome to share their thoughts.
By including the community, we’ve done a fantastic job of turning Corinna from an interesting sideshow to something that is (mostly) popular with the Perl community. If we can bring her over the finish line, we have something that is likely to be included in the Perl core as an experimental project. You have to ask for it by name:
use feature 'class';
class Foo {
...
}
And then you get all the lovely OO goodies in a powerful, declarative syntax.
We’re soooooo close to being able to propose an RFC that I am loathe to throw a wrench in the works, but I must. I must because Kim is very, very unhappy with Corinna.

Please note that much of this is largely derived from emails I’ve swapped with Damian Conway . I’ve rewritten it considerably, but the core of this is him noting inconsistencies that have been discussed on the IRC channel, but not put together conherently. Corinna has evolved with some serious inconsistencies and the time to consider fixing them is now, not after it’s released.
Corinna, as some of you may know, was chosen as the name of this project because my nom de guerre, is “Ovid” and he wrote poems to Corinna, a love interest (if you’re familiar with the poetry, you know I’m keeping this family-friendly). Kim isn’t jealous of Corinna. She’s furious because Corinna, after literally years of design, is breaking some cardinal rules of consistency. So, let’s dig into that.
So let’s look at the way we declare things in Perl. In particular, we’ll look
at my
variables, subroutines, and packages.
my $answer = 42;
sub douglas_adams { ... }
package Restaurant { ... }
Those all seem different, but we start declaring what type of thing we have: a variable, a subroutine, or a package. Then we follow that up with the name of the thing, followed by the optional set up of that thing.
But what if we want to modify how those things behave? Attributes have been
alternately proposed and rejected by many developers, but if you use
threads::shared
in Perl, you can declare a variable as shared across
threads:
my $answer :shared = 42;
What if you want to declare a subroutine as an lvalue?
sub douglas_adams :lvalue {...}
Or declaratively state the version of a package without using the procedural
$VERSION
assignment?
package Restaurant v3.1.4 { ... }
In fact, if we continue down this road, we see a pattern start to emerge:
| keyword | identifier | modifiers? | setup? |
|---|---|---|---|
| my | $lexvar | :shared | |
| our | $packvar | :Tracked | = 0 |
| state | $statevar | :Readonly | = 1 |
| sub | action | :lvalue | () {...} |
| package | Namespace | v1.2.3 | {...} |
| format | Report | = ... . |
KIM stands for “Keyword”, “Identifier”, and “Modifier” (yes, it should be “KIMS”, but I like the “Kim versus Corinna” description. Sue me.)
Kim likes consistency. You must always declare the kind of thing you’re going to use and then name it. You can then optionally modify its base behavior and then optionally set it up. Very, very consistent:
KEYWORD IDENTIFIER MODIFIERS SETUP
Of course, you can point to plenty of areas where Perl is not consistent, but Corinna is designed to improve the Perl language, not add to the inconsistency, so let’s look at a few examples:
| keyword | identifier | modifiers? | setup? |
|---|---|---|---|
| role | Tracked | {...} | |
| class | Root | {...} | |
| slot | $msg | :param | |
| slot | $handler | :handles(exists delete) | = Handler->new; |
| slot | $size | :reader :param | = 100; |
| slot | $created | :reader | = time; |
| method | is_root () | {...} | |
| method | obj_count | :common () | {...} |
| method | insert | :private ($key,$value) | {...} |
| method | show ($msg) | {...} | |
| method | obj_count | :overrides :common () | {...} |
So that’s actually looking pretty good. Corinna is developing with a clear, consistent KIM syntax. But if that was all, this wouldn’t be a helpful article. That’s the good; it’s time to look at the bad. And maybe the ugly.
This Ain’t Kim
Let’s look at a few examples of inconsistencies. We’ll start with putting the modifier first.
| modifier | keyword | identifier | setup |
|---|---|---|---|
| abstract | class | Counter | {...} |
And let’s mix up keywords and modifiers.
| keyword | identifier | keyword as modifiers | setup |
|---|---|---|---|
| class | Handler | isa Counter does Tracked | {...} |
Let’s use modifers plus keywords plus identifiers plus modifiers plus ...
| modifier | keyword | identifier | modifiers | setup |
|---|---|---|---|---|
| before | method | obj_count | :overrides :common () | { warn “Counting...“; } |
| after | method | obj_count | :overrides :common () | { warn “...done”; } |
| around | method | obj_count | :overrides :common () | { return 1 + $self->$ORIG(); } |
So, yeah. Damian pointed all of this out to me and he’s right. Corinna is close, but there are syntactical inconsistencies which, if agreed that they should be addressed, should be addressed before an RFC, not after.
Turning Corinna into Kim
The name’s still Corinna, but she needs KIM.
When I started converting Tau Station code to (in)consistently use SVO syntax, it made it much easier to maintain. Doing the same thing with Corinna is worthwhile.
So, how do we address all these inconsistencies? Corinna semantics are OK. We just need some tweaks to the syntax.
| keyword | identifier | modifiers? | setup? |
|---|---|---|---|
| class | Counter | :abstract | {...} |
| class | Handler | :isa(Counter) :does(Tracked) | {...} |
| method | obj_count | :before :overrides :common | () { warn “Counting...“; } |
| method | obj_count | :after :overrides :common | () { warn “...done”; } |
| method | obj_count | :around :overrides :common | () { return 1 + $self->$ORIG(); } |
And here’s a slightly modified example from Damian showing this more consistent syntax:
role Tracked {
slot $msg :param;
method report () { $self->show($msg++) }
method show; # required
}
class Root {
method is_root () { return 1; }
}
class Counter :abstract {
slot $obj_count :common :reader = 0;
ADJUST { $obj_count++ }
DESTRUCT { $obj_count-- }
}
class Handler :isa(Counter) :does(Tracked) {
slot $handler :handles(exists delete) = Handler->new;
slot $size :reader :param = 100;
slot $created :reader = time;
ADJUST { croak("Too small") if $size < 1; }
DESTRUCT { $handler->shutdown; }
method insert :private ($key, $value ) {
if ( ! $self->exists($key) ) {
$handler->set( $key, $value );
}
}
method show ($msg) { say $msg; }
method obj_count :common :overrides () { $self->next::method() - 42; }
method obj_count :common :before () { warn "Counting..."; }
method obj_count :common :around () { return 1 + $self->$ORIG(); }
method obj_count :common :after () { warn "...done"; }
}
Conclusion
As you can see from the sample code, this still looks like Corinna. We have the semantics and syntax, but do we have the community? The changes aren’t huge, but they might prove controversial because Corinna would again be changing. But I think it’s changing for the better. Further, by establishing the KIM principle now, further upgrades to the Perl language can have guidance on maintaining consistency.


Threading
Scheduling work to be performed on another thread is straightforward in Tempo. The Thread operator must be used from a continuous block, and it is passed an inner continuous block which is executed on a new thread. A short pseudocode example:
main()
{
...
thread
{
every(TimeSpan.FromSeconds(60))
{
PerformSlowOperation();
}
}
}
In this example, some slow work is performed in a background thread every 60 seconds, but does not interrupt the main thread. It is common to need a thread nested within a whilst operator, so Tempo provides the WhilstThread operator which combines these into one statement.
Synchronization
By default, Tempo assumes that all work is thread local. This reflects the library's approach to scaling: Use isolation where possible, and synchronize where necessary. In making isolation the default, Tempo can schedule and execute thread local work efficiently. Eventually some communication between threads will be necessary, and only at this point is synchronization used.
In Tempo, threads communicate via shared cells. This means there are two places where synchronization
must be considered: when a shared cell is observed by a continuous block, and when the contents of a shared
cell is updated by an imperative block. The class Shared<T>
is provided to wrap cells that are to be
shared across threads.
In order to safely update a shared cell, it must first be locked. Tempo provides the Lock operator so that a thread can ensure exclusive access to all shared cells involved in an update. If any of the cells are currently locked elsewhere, the body of the lock operator will be put in a queue until the cells become available. This means that in Tempo, lock contention does not block a thread - instead only the block that requires the lock will wait and the thread will continue to schedule other work until it is possible to lock all the required cells. The lock operator should not be used from within another lock operator. Instead, the outermost lock operator should lock all the required data. Following this rule means that deadlock cannot occur, although it is still possible for a long-running operation to starve other threads of access to locked cells.


DSM Object¶
This is the root document object of the DSM document.
- Fields:
Field Name Type Description version string REQUIRED. This string MUST be the semantic version number of the DSM Specification version that the DSM document uses. The DSM field SHOULD be used by tooling specifications and clients to interpret the DSM document params Map[string,any] params_ field is a map that contains parameter definition to configure DSM document and `Parsing Element`_s. transformations Map[string,`Transformation Element`_] Deceleration of Map contains transformationCode_ as key, and `Transformation Element`_ as value. `Transformation Element`_ holds lookup table to transform value from `Source Document`_ to destination document. functions Map[string,Function_] Deceleration of Map contains function_ name as key, and function deceleration as value. functions are used for custom parsing or calling services with parsed data. Functions implements FunctionExecutor interface. fragments Map [String, `Parsing Element`_ ] A map contains declaration of reusable `Parsing Element`_. The fragment definition can be referenced with $ref_ field while defining `Parsing Element`_. result `Parsing Element`_ REQUIRED. The entry point of `Parsing Element`_ declarations. The result field defines structure of the output. $extends string `$extends`_ field is used for import external DSM document.
params¶
params field is a map that contains parameter definition to configure DSM document and `Parsing Element`_. The key of params map is string and case sensitive. The value of params map can be any type of json object(int, boolean, object, array) accepted by JSON and YAML specification.
Example DSM document that contains params.
YAML
version: 1.0
params:
dateFormat: dd.MM.yyyy
rootPath: fooBar/foo
category:
foo: bar
acceptedCountryCode: [TR,US,FR]
JSON
{
"version": 1.0,
"params":{
"dateFormat":"dd.MM.yyyy",
"rootPath":"fooBar/foo",
"category":{
"foo":"bar"
},
"acceptedCountryCode": ["TR","US","FR"]
}
}
transformations¶
Deceleration of Map contains transformationCode_ as key, and `Transformation Element`_ as value. `Transformation Element`_ holds lookup table to transform value from `Source Document`_ to destination document.
Example CF document that contains transformations
YAML
version: 1.0 transformations: COUNTRY_CODE_TO_NAME: map: DEFAULT: Other TR: Turkey US: United States
JSON
{
"version": 1.0,
"transformations":{
"COUNTRY_CODE_TO_NAME":{
"map":{
"TR":"Turkey",
"US":"United States",
"DEFAULT":"Other"
}
}
}
}
functions¶
Deceleration of Map contains function_ name as key, and function deceleration as value. functions are used for custom parsing or calling services with parsed data. Functions implements FunctionExecutor interface.
Example CF document that contains functions
YAML
version: 1.0 functions: insertProduct: com.example.InsertProduct approveOrder: com.example.ApproveOrder
JSON
{
"version": 1.0,
"functions":{
"insertProduct":"com.example.InsertProduct",
"approveOrder":"com.example.ApproveOrder"
}
}
fragments¶
A map contains declaration of reusable `Parsing Element`_. The fragment definition can be referenced with `$ref`_ field while defining `Parsing Element`_.
Example CF document that contains functions
YAML
version: 1.0
fragments:
product:
fields:
id: string
name: string
price: double
JSON
{ "version": 1.0, "fragments":{ "product":{ "fields":{ "id":"string", "name":"double", "price":"double" } } } }
result¶
REQUIRED. The entry point of `Parsing Element`_ declarations. The result field defines structure of the output.
Example CF document that contains result
YAML
version: 1.0 result: type: object path: / fields: id: string name: string price: double
JSON
{
"version": 1.0,
"result":{
"type":"object",
"path":"/"
"fields":{
"id":"string",
"name":"double",
"price":"double"
}
}
}
$extends¶
$extends field is used for import external DSM document to current DSM document. it’s value is basically relative path or URI definition of external DSM document. if it’s value start with “$” sing, it is accepted as an expression_ and resolved by expression resolver. External DSM document will merged_ into current DSM document. $extends can also be list of path or URI. Merge_ process start from first element to last element. Firstly current DSM document merged_ with first element then result of merge_ process extended to second element etc..
Example CF document that contains extends
YAML
version: 1.0
$extends: /foo/bar/external.yaml
or
version: 1.0
params:
rootPath: /bar/foo/
$extends:
- /foo/bar/external.yaml
- $params.rootPath.concat("externalWithExpression.yaml")
JSON
{
"version": 1.0,
"$extends": "/foo/bar/external.json"
}
or
{
"version": 1.0,
"params":{
"rootPath":"/bar/foo/"
},
"$extends": ["/foo/bar/external.json","$params.rootPath.concat('externalWithExpression.json')"]
}


Mini Wimbledon!
Click below to play the game, if you score well, you will appear near the top of the hiscore list!
Good Luck! Click Here to play the game Click Here to return to the website


Notebooks
Story: Young man of the Early Race put into a mouse skin and becomes a lion
Young man of the Early Race put into a mouse skin and becomes a lion
Title
Young man of the Early Race put into a mouse skin and becomes a lion
Collection
Summary
Children push a youth into the skin of a Fieldmouse and tell him to 'trot away', which he does, becoming a Lion. The children tell the Lion to go and lie down, which he does. The Lion charges the people and runs at his brother's wife, biting her in the head and dragging her into the reeds.
Comments
1) p.7526v: |han≠kass'o was told this story by his mother (|xabbi-an), who he thinks heard it from her mother (≠kammi); on the Fieldmouse's name (it is 'mouse' and it has no other), 2) pp.7528v-7529v: an explanation of !kuppem !kuppem (and calling to the fieldmice), 3) p.7537v: the Tarru-ggu or akkedis (the sister-in-law is one), 4) This story is found in Book VIII-17
Contributors
|han≠kass'o (Klein Jantje) (VIII)
Date
20 September 1878 (started)
Categories
Keywords
Early Race (the First Bushmen) , Early Race (the children of) , Early Race (the youths of) , Early Race (and the young man of put into a mouse skin who becomes a lion) , Early Race (and transformation) , Early Race (the Fieldmice are people of) , Early Race (the Lion is a person of) , Fieldmice (the method of calling them out of their holes) , Fieldmice (are shot at, killed and skinned by the children of the Early Race) , Fieldmice (resemble lions) , Fieldmice (the youth of the Early Race put into a mouse skin who becomes a lion) , Fieldmice (their name is 'mouse') , Fieldmice (are people of the Early Race) , Lion (the youth of the Early Race put into a mouse skin who becomes a lion) , Lion (the youth becomes one to kill his sister-in-law) , Lion (lives in the reeds) , Lion (chases his 'comrades') , Lion (the nature and habits of lions) , mice (the youth of the Early Race is put into a mouse skin and becomes a lion) , mice (the Fieldmice) , children (of the Early Race put their comrade into a Fieldmouse skin and he becomes a lion) , children (kill and skin the Fieldmice) , youth (young man) , youth (his sister-in-law is a lizard) , youth (who becomes a lion in order to kill his sister-in-law) , youth (is put into a Fieldmouse skin and becomes a lion) , youth (is a person of the Early Race) , transformation (of the youth put into a mouse skin who becomes a lion) , lizard (the sister-in-law of the youth is one) , lizard (a description of) , lizard (the Tarru-ggu, or akkedis) , names (a lizard called the Tarru-ggu, or akkedis) , names (the Fieldmouse's name is 'Mouse') , names (and the young man of the Early Race put into a mouse skin who becomes a lion)
Story Pages
7527-7541


Keywords: RDF, RDF Graph, RDF Dataset, validation, formal schema, ShEx, RDF Validation, Z Specification Language
The Shape Expressions Language (ShEx) is used to specify formal constraints on the content of RDF graphs and are intended to be used to validate RDF documents, communicate expected graph patterns for interfaces and to generate forms and validation code. ShEx can be used to:
Information about the use, grammar and syntax of ShEx can be found at http://www.w3.org/2013/ShEx. The purpose of this document is to describe the formal semantics of the ShEx language using the Z specification language. We begin with a formal specification of the characteristics of an RDF Graph that are referenced by ShEx.
Using the formal definitions in RDF 1.1 Concepts and Abstract Syntax[1], we begin with:
“An RDF graph is a set of RDF Triples”
Formally:
“An RDF triple consists of three components:
“‘... IRIs, literals and blank nodes are distinct and distinguishable.”
The ShEx language treats IRIs and blank nodes as primitive types, so we can formally define them as Z free types:
The ShEx language can express constraints on both the type and content of literals, so we need to model these separately. Starting with:
“A literal in an RDF graph consists of two or three elements:
We model this by defining String and LanguageTag as free types:
“IRIs, literals and blank nodes are collectively known as RDF terms
The ShEx language uses the following functions:
– return set of triples in a graph triples whose subject is a given RDFTerm
– return set of triples in a graph triples whose object is a given RDFTerm
The following URI’s are referenced explicitly in the ShEx implementation:
This completes the formal definition of Graph, Triple, RDFTerm and their components, which we can now use to describe the relationship between an ShEx Schema and an RDF graph.
A Shape Expression Schema is a collection of labeled rules where exactly one rule in the collection is identified as the outermost or “starting” rule. In addition, any rule that is referenced within the Schema is also itself a member of the Schema Formally:
While existing ShEx implementations define a rule Label as being either an IRI or a BlankNode, the type of Label does not impact the evaluation semantics. For our purposes, we can simply define it as a separate free type:
The validity of a given RDF Graph is determined by taking the start Rule of a ShEx Schema and a reference IRI and evaluating the validity of the Rule against the supplied graph.
Formally, the evaluate function takes a Schema, a Graph and a reference IRI and, if the start Rule in the Schema, in the context of the starting Schema and graph, returns either nomatch (z) or pass (p) then the function returns pass. In all other cases, the function returns fail (f ).
A ShEx Rule is a set of constraints that can be evaluated against a reference RDFTerm in the context of a given Schema and RDF Graph:
Formally, the evalRule function takes an EvalContext, a reference RDFTerm and a Rule and returns one of the following:
The ArcRule is used to select the subset of the graph having a given predicate or predicates and to determine whether the cardinality and/or “type” of this subset matches a supplied criteria. The rule itself consists of a PredicateFilter to select the triples, an ObjectSpecification to evaluate the result, a optional min and max cardinality and a (possibly empty) set of Actions:
A PredicateFilter can be one of:
ObjectSpecification specifies a set of possible values for an RDFTerm and takes one of the following forms:
– evaluates the cardinality the supplied graph.
evalObjectSpecification – returns pass (p) if all of the triples in a Graph match the supplied ObjectSpecification, otherwise fail (f )
evalValueType – returns pass if the supplied RDFTerm is:
evalTermSet – return p if the supplied RDFTerm is a member of MatchValue
evalTermWild – return pass (p) if the supplied RDFTerm is not a member of MatchValue.
evalTermReference – return p if the subgraph of the EvalContext graph whose subjects match the supplied RDFTerm satisfies the ValueReference rule.
The RevArcRule is used to select the subset of the graph having a given predicate or predicates and to determine whether the cardinality and/or “type” of this subset matches a supplied criteria. The rule itself consists of a PredicateFilter to select the triples, an SubjectSpecification to evaluate the result, a optional min and max cardinality and a (possibly empty) set of Actions:
SubjectSpecification specifies a set of possible values for an RDFTerm and takes one of the following forms:
paragraphevalSubjectSpecification – returns pass (p) if all of the triples in a Graph match the supplied SubjectSpecification, otherwise fail (f )
A GroupRule serves two purposes. The first is to declare that a referenced rule is to be treated as “optional”, which, in this case means that if (a) the referenced rule returned dunno (∅), (meaning an ArcRule was encountered that had no matching predicates and a non-zero minimum cardinality) the group rule returns nomatch (z). An optional GroupRule also treats an error situation as a fail (f ).
The second purpose of a group rule is to allow a set of external actions to be evaluated whenever the referenced rule returns pass (p).
An AndRule consists of a set of one or more Rules, whose evaluation is determined by
the following table:
| And | ∅ | z | f | p | ε |
| ∅ | ∅ | ∅ | f | f | ε |
| z | ∅ | z | f | p | ε |
| f | f | f | f | f | ε |
| p | f | p | f | p | ε |
| ε | ε | ε | ε | ε | ε |
The formal implementation of which will be realized in the corresponding function:
Observing that the above table is a monoid with nomatch (z) as an identity element, evalAndRule can be applied using the standard functional pattern:
An XorRule consists of a set of one or more Rules, whose evaluation is determined by
the following table:
| Xor | ∅ | z | f | p | ε |
| ∅ | ∅ | z | ∅ | p | ε |
| z | z | z | z | p | ε |
| f | ∅ | z | f | p | ε |
| p | p | p | p | ε | ε |
| ε | ε | ε | ε | ε | ε |
The dispatch function allows the evaluation / execution of arbitrary external “Actions”. While the evaluation of an Action can (obviously) have side effects outside the context of the ShEx environment, it must be side effect free within the execution context. In particular, an Action may not change anything in the EvalContext The action dispatcher exists to allow external events to happen. Parameters:
The dispatch function usually returns pass (p) or fail (f ), although there may also be cases for other OptValidity values in certain circumstances. The dispatch function always returns pass (p) if the set of actions is empty.
The foldr function is the standard functional pattern, which takes a binary function of type T, an identity function for type T, a sequence of type T and returns the result of applying the function to the right to left pairs of the sequence.
The map function takes a function from type A to type B and applies it to all members in the supplied sequence
Z uses the notion of free type definitions in the form:
One way to represent optional values is a set with one member. We take that route here and introduce a bit of syntactic sugar to show our intent:
And a shorthand for addressing the content:
1. Richard Cyganiak and David Wood. RDF 1.1 concepts and abstract syntax - generalized rdf triples, graphs, and datasets. World Wide Web Consortium, Working Draft WD-rdf11-concepts-20130723, August 2013.
2. M. Dürst and M. Suignard. Internationalized resource identifiers (iris). RFC, January 2005.
3. RA Phillips and M. Davis. Tags for identifying language. IETF Best Current Practices, September 2009.


--- layout: post title: 'Mobile 2.0 Europe: Context Panel' date: 2009-06-19 00:00:00 categories: business interfaces-&-interaction mobile ---
Mobile 2.0 Europe: Context Panel
Moderator: Raimo van der Klein, SPRXMobile
Gregr Skibiski, Sense Networks
Tommy Ahers, Vodafone (ex-Zyb)
Felix Petersen, Nokia Berlin
Ted Morgan, SkyHook
Xavier Carrillo Costa, Digital Legends
XCC: we spend a lot of money simulating the real world. Now we're connecting with the real world, and it's changing the game paradigm.
TM: Have difficulty figuring out some behaviour. We see some locations which have huge numbers of lookups, but can't work out why. One of our heaviest location users on the iPhone is the RIM HQ.
FP: We have a successful mapping product. We realised a couple of years back that we didn't need to license traffic data, we could gather it ourselves from looking at behaviour of users with our product. Google built a product on the back of inferring meaning from links between pages; we can do the same with geographic links.
TA: Heading up location team at Vodafone now. When I promised to change Vodafone from the inside, I didn't realise how big it was :) Enabling location apps through the web framework.
GS: We get lots of data from carriers around location. 4-5% of people will use an app 15 times on the iPhone. So can we use combinations of location and other date to predict which apps people will use? There is a link between historical location usage and app usage - e.g. for directory applications, someone moving around a lot is more likely to use one.
Q: Where do you get the data to predict churn, age, sex?
GS: Direct from carriers. Usage of the data is tightly regulated, but for an internal purpose like churn measurement is allowed. External stuff like marketing has to be opt-in.
Q: The US is not very regulated when it comes to privacy. Can you give us examples of data extracted for LBS in Europe, compliant with DPA and Privacy laws?
A: (TA) Latitude. (FP) At Nokia we opted against doing a friend-finder product. The issue is tracking vs publishing; Latitude seems a little naive.
RVDK: Location updates are social behaviour - when people update their location manually, they're saying something.
FP: Manual location updates are more interesting and more relevant.
Q: How far can prediction go?
GS: We take a group of people, a year of behaviour, crunch the data, then work out if they e.g. like rap music, go out at night, and can see we've accurately predicted what they like.
FP: I have to make an effort to physically go somewhere - so it has a lot of meaning. Dopplr are doing interesting stuff with location and the social graph; I tried it and they predicted places I'd like with surprising accuracy, based on very little data.
TM: Most advertising is based on your home, which is where you spend very little time.
FP: But this doesn't matter. We used to derive intent from demographic data, now we can predict it from real behaviour.
XCC: In the console world we manually mine data.
Q: The location visualisation and predictions are fascinating. Can you say anything about apps that generated swarm behaviour?
GS: Talks about taxi visualisations; these bring a feedback loop which modify behaviour.
TM: We've not seen anyone build swarm behaviour, but don't have access to the data in realtime so it's hard.
Q: Context is more than location, it's about a network too.
FP: We've seen lots of interesting examples... we can derive more than location from the phone. We form social graphs every day by interacting, the explicit "we are friends" of Facebook is very raw. If we could mine your everyday life we could be more subtle.


Subcontractor declaration for 2017 to 2018
You need to make a declaration even if you do not use subcontractors.
You must also update your declaration if your subcontracting arrangements change during the year.
You need to make a declaration even if you do not use subcontractors.
You must also update your declaration if your subcontracting arrangements change during the year.


PERLOTHRTUT
Section: Perl Programmers Reference Guide (1)Updated: 2009-04-12
Index Return to Main Contents
NAME
perlothrtut - old tutorial on threads in PerlDESCRIPTION
WARNING: This tutorial describes the old-style thread model that was introduced in release 5.005. This model is deprecated, and has been removed for version 5.10. The interfaces described here were considered experimental, and are likely to be buggy.For information about the new interpreter threads (``ithreads'') model, see the perlthrtut tutorial, and the threads and threads::shared modules.
You are strongly encouraged to migrate any existing threads code to the new model as soon as possible.
What Is A Thread Anyway?
A thread is a flow of control through a program with a single execution point.Sounds an awful lot like a process, doesn't it? Well, it should. Threads are one of the pieces of a process. Every process has at least one thread and, up until now, every process running Perl had only one thread. With 5.005, though, you can create extra threads. We're going to show you how, when, and why.
Threaded Program Models
There are three basic ways that you can structure a threaded program. Which model you choose depends on what you need your program to do. For many non-trivial threaded programs you'll need to choose different models for different pieces of your program.Boss/Worker
The boss/worker model usually has one `boss' thread and one or more `worker' threads. The boss thread gathers or generates tasks that need to be done, then parcels those tasks out to the appropriate worker thread.This model is common in GUI and server programs, where a main thread waits for some event and then passes that event to the appropriate worker threads for processing. Once the event has been passed on, the boss thread goes back to waiting for another event.
The boss thread does relatively little work. While tasks aren't necessarily performed faster than with any other method, it tends to have the best user-response times.
Work Crew
In the work crew model, several threads are created that do essentially the same thing to different pieces of data. It closely mirrors classical parallel processing and vector processors, where a large array of processors do the exact same thing to many pieces of data.This model is particularly useful if the system running the program will distribute multiple threads across different processors. It can also be useful in ray tracing or rendering engines, where the individual threads can pass on interim results to give the user visual feedback.
Pipeline
The pipeline model divides up a task into a series of steps, and passes the results of one step on to the thread processing the next. Each thread does one thing to each piece of data and passes the results to the next thread in line.This model makes the most sense if you have multiple processors so two or more threads will be executing in parallel, though it can often make sense in other contexts as well. It tends to keep the individual tasks small and simple, as well as allowing some parts of the pipeline to block (on I/O or system calls, for example) while other parts keep going. If you're running different parts of the pipeline on different processors you may also take advantage of the caches on each processor.
This model is also handy for a form of recursive programming where, rather than having a subroutine call itself, it instead creates another thread. Prime and Fibonacci generators both map well to this form of the pipeline model. (A version of a prime number generator is presented later on.)
Native threads
There are several different ways to implement threads on a system. How threads are implemented depends both on the vendor and, in some cases, the version of the operating system. Often the first implementation will be relatively simple, but later versions of the OS will be more sophisticated.While the information in this section is useful, it's not necessary, so you can skip it if you don't feel up to it.
There are three basic categories of threads-user-mode threads, kernel threads, and multiprocessor kernel threads.
User-mode threads are threads that live entirely within a program and its libraries. In this model, the OS knows nothing about threads. As far as it's concerned, your process is just a process.
This is the easiest way to implement threads, and the way most OSes start. The big disadvantage is that, since the OS knows nothing about threads, if one thread blocks they all do. Typical blocking activities include most system calls, most I/O, and things like sleep().
Kernel threads are the next step in thread evolution. The OS knows about kernel threads, and makes allowances for them. The main difference between a kernel thread and a user-mode thread is blocking. With kernel threads, things that block a single thread don't block other threads. This is not the case with user-mode threads, where the kernel blocks at the process level and not the thread level.
 Threads that block performing I/O, for example, won't block threads that are doing other things. Each process still has only one thread running at once, though, regardless of how many CPUs a system might have.
Since kernel threading can interrupt a thread at any time, they will uncover some of the implicit locking assumptions you may make in your program. For example, something as simple as "$a = $a + 2" can behave unpredictably with kernel threads if $a is visible to other threads, as another thread may have changed $a between the time it was fetched on the right hand side and the time the new value is stored.
Multiprocessor Kernel Threads are the final step in thread support. With multiprocessor kernel threads on a machine with multiple CPUs, the OS may schedule two or more threads to run simultaneously on different CPUs.
This can give a serious performance boost to your threaded program, since more than one thread will be executing at the same time. As a tradeoff, though, any of those nagging synchronization issues that might not have shown with basic kernel threads will appear with a vengeance.
In addition to the different levels of OS involvement in threads, different OSes (and different thread implementations for a particular OS) allocate CPU cycles to threads in different ways.
Cooperative multitasking systems have running threads give up control if one of two things happen. If a thread calls a yield function, it gives up control. It also gives up control if the thread does something that would cause it to block, such as perform I/O. In a cooperative multitasking implementation, one thread can starve all the others for CPU time if it so chooses.
Preemptive multitasking systems interrupt threads at regular intervals while the system decides which thread should run next. In a preemptive multitasking system, one thread usually won't monopolize the CPU.
On some systems, there can be cooperative and preemptive threads running simultaneously. (Threads running with realtime priorities often behave cooperatively, for example, while threads running at normal priorities behave preemptively.)
What kind of threads are perl threads?
If you have experience with other thread implementations, you might find that things aren't quite what you expect. It's very important to remember when dealing with Perl threads that Perl Threads Are Not X Threads, for all values of X. They aren't POSIX threads, or DecThreads, or Java's Green threads, or Win32 threads. There are similarities, and the broad concepts are the same, but if you start looking for implementation details you're going to be either disappointed or confused. Possibly both.This is not to say that Perl threads are completely different from everything that's ever come before---they're not. Perl's threading model owes a lot to other thread models, especially POSIX. Just as Perl is not C, though, Perl threads are not POSIX threads. So if you find yourself looking for mutexes, or thread priorities, it's time to step back a bit and think about what you want to do and how Perl can do it.
Threadsafe Modules
The addition of threads has changed Perl's internals substantially. There are implications for people who write modules---especially modules with XS code or external libraries. While most modules won't encounter any problems, modules that aren't explicitly tagged as thread-safe should be tested before being used in production code.Not all modules that you might use are thread-safe, and you should always assume a module is unsafe unless the documentation says otherwise. This includes modules that are distributed as part of the core. Threads are a beta feature, and even some of the standard modules aren't thread-safe.
If you're using a module that's not thread-safe for some reason, you can protect yourself by using semaphores and lots of programming discipline to control access to the module. Semaphores are covered later in the article. Perl Threads Are Different
Thread Basics
The core Thread module provides the basic functions you need to write threaded programs. In the following sections we'll cover the basics, showing you what you need to do to create a threaded program. After that, we'll go over some of the features of the Thread module that make threaded programming easier.Basic Thread Support
Thread support is a Perl compile-time option-it's something that's turned on or off when Perl is built at your site, rather than when your programs are compiled. If your Perl wasn't compiled with thread support enabled, then any attempt to use threads will fail.Remember that the threading support in 5.005 is in beta release, and should be treated as such. You should expect that it may not function entirely properly, and the thread interface may well change some before it is a fully supported, production release. The beta version shouldn't be used for mission-critical projects. Having said that, threaded Perl is pretty nifty, and worth a look.
Your programs can use the Config module to check whether threads are enabled.
A possibly-threaded program using a possibly-threaded module might have code like this:
use Config; use MyMod; if ($Config{usethreads}) { # We have threads require MyMod_threaded; import MyMod_threaded; } else { require MyMod_unthreaded; import MyMod_unthreaded; }
Since code that runs both with and without threads is usually pretty messy, it's best to isolate the thread-specific code in its own module. In our example above, that's what MyMod_threaded is, and it's only imported if we're running on a threaded Perl.
Creating Threads
The Thread package provides the tools you need to create new threads. Like any other module, you need to tell Perl you want to use it; use Thread imports all the pieces you need to create basic threads.The simplest, straightforward way to create a thread is with new():
use Thread; $thr = Thread->new( \&sub1 ); sub sub1 { print "In the thread\n"; }
The new() method takes a reference to a subroutine and creates a new thread, which starts executing in the referenced subroutine. Control then passes both to the subroutine and the caller.
If you need to, your program can pass parameters to the subroutine as part of the thread startup. Just include the list of parameters as part of the "Thread::new" call, like this:
use Thread; $Param3 = "foo"; $thr = Thread->new( \&sub1, "Param 1", "Param 2", $Param3 ); $thr = Thread->new( \&sub1, @ParamList ); $thr = Thread->new( \&sub1, qw(Param1 Param2 $Param3) ); sub sub1 { my @InboundParameters = @_; print "In the thread\n"; print "got parameters >", join("<>", @InboundParameters), "<\n"; }
The subroutine runs like a normal Perl subroutine, and the call to new Thread returns whatever the subroutine returns.
The last example illustrates another feature of threads. You can spawn off several threads using the same subroutine. Each thread executes the same subroutine, but in a separate thread with a separate environment and potentially separate arguments.
The other way to spawn a new thread is with async(), which is a way to spin off a chunk of code like eval(), but into its own thread:
use Thread qw(async); $LineCount = 0; $thr = async { while(<>) {$LineCount++} print "Got $LineCount lines\n"; }; print "Waiting for the linecount to end\n"; $thr->join; print "All done\n";
You'll notice we did a use Thread qw(async) in that example. async is not exported by default, so if you want it, you'll either need to import it before you use it or fully qualify it as Thread::async. You'll also note that there's a semicolon after the closing brace. That's because async() treats the following block as an anonymous subroutine, so the semicolon is necessary.
Like eval(), the code executes in the same context as it would if it weren't spun off. Since both the code inside and after the async start executing, you need to be careful with any shared resources. Locking and other synchronization techniques are covered later.
Giving up control
There are times when you may find it useful to have a thread explicitly give up the CPU to another thread. Your threading package might not support preemptive multitasking for threads, for example, or you may be doing something compute-intensive and want to make sure that the user-interface thread gets called frequently. Regardless, there are times that you might want a thread to give up the processor.Perl's threading package provides the yield() function that does this. yield() is pretty straightforward, and works like this:
use Thread qw(yield async); async { my $foo = 50; while ($foo--) { print "first async\n" } yield; $foo = 50; while ($foo--) { print "first async\n" } }; async { my $foo = 50; while ($foo--) { print "second async\n" } yield; $foo = 50; while ($foo--) { print "second async\n" } };
Waiting For A Thread To Exit
Since threads are also subroutines, they can return values. To wait for a thread to exit and extract any scalars it might return, you can use the join() method.
use Thread; $thr = Thread->new( \&sub1 ); @ReturnData = $thr->join; print "Thread returned @ReturnData"; sub sub1 { return "Fifty-six", "foo", 2; }
In the example above, the join() method returns as soon as the thread ends. In addition to waiting for a thread to finish and gathering up any values that the thread might have returned, join() also performs any OS cleanup necessary for the thread. That cleanup might be important, especially for long-running programs that spawn lots of threads. If you don't want the return values and don't want to wait for the thread to finish, you should call the detach() method instead. detach() is covered later in the article.
Errors In Threads
So what happens when an error occurs in a thread? Any errors that could be caught with eval() are postponed until the thread is joined. If your program never joins, the errors appear when your program exits.Errors deferred until a join() can be caught with eval():
use Thread qw(async); $thr = async {$b = 3/0}; # Divide by zero error $foo = eval {$thr->join}; if ($@) { print "died with error $@\n"; } else { print "Hey, why aren't you dead?\n"; }
eval() passes any results from the joined thread back unmodified, so if you want the return value of the thread, this is your only chance to get them.
Ignoring A Thread
join() does three things: it waits for a thread to exit, cleans up after it, and returns any data the thread may have produced. But what if you're not interested in the thread's return values, and you don't really care when the thread finishes? All you want is for the thread to get cleaned up after when it's done.In this case, you use the detach() method. Once a thread is detached, it'll run until it's finished, then Perl will clean up after it automatically.
use Thread; $thr = Thread->new( \&sub1 ); # Spawn the thread $thr->detach; # Now we officially don't care any more sub sub1 { $a = 0; while (1) { $a++; print "\$a is $a\n"; sleep 1; } }
Once a thread is detached, it may not be joined, and any output that it might have produced (if it was done and waiting for a join) is lost.
Threads And Data
Now that we've covered the basics of threads, it's time for our next topic: data. Threading introduces a couple of complications to data access that non-threaded programs never need to worry about.Shared And Unshared Data
The single most important thing to remember when using threads is that all threads potentially have access to all the data anywhere in your program. While this is true with a nonthreaded Perl program as well, it's especially important to remember with a threaded program, since more than one thread can be accessing this data at once.Perl's scoping rules don't change because you're using threads. If a subroutine (or block, in the case of async()) could see a variable if you weren't running with threads, it can see it if you are. This is especially important for the subroutines that create, and makes "my" variables even more important. Remember---if your variables aren't lexically scoped (declared with "my") you're probably sharing them between threads.
Thread Pitfall: Races
While threads bring a new set of useful tools, they also bring a number of pitfalls. One pitfall is the race condition:
use Thread; $a = 1; $thr1 = Thread->new(\&sub1); $thr2 = Thread->new(\&sub2); sleep 10; print "$a\n"; sub sub1 { $foo = $a; $a = $foo + 1; } sub sub2 { $bar = $a; $a = $bar + 1; }
What do you think $a will be? The answer, unfortunately, is ``it depends.'' Both sub1() and sub2() access the global variable $a, once to read and once to write. Depending on factors ranging from your thread implementation's scheduling algorithm to the phase of the moon, $a can be 2 or 3.
Race conditions are caused by unsynchronized access to shared data. Without explicit synchronization, there's no way to be sure that nothing has happened to the shared data between the time you access it and the time you update it. Even this simple code fragment has the possibility of error:
use Thread qw(async); $a = 2; async{ $b = $a; $a = $b + 1; }; async{ $c = $a; $a = $c + 1; };
Two threads both access $a. Each thread can potentially be interrupted at any point, or be executed in any order. At the end, $a could be 3 or 4, and both $b and $c could be 2 or 3.
Whenever your program accesses data or resources that can be accessed by other threads, you must take steps to coordinate access or risk data corruption and race conditions.
Controlling access: lock()
The lock() function takes a variable (or subroutine, but we'll get to that later) and puts a lock on it. No other thread may lock the variable until the locking thread exits the innermost block containing the lock. Using lock() is straightforward:
use Thread qw(async); $a = 4; $thr1 = async { $foo = 12; { lock ($a); # Block until we get access to $a $b = $a; $a = $b * $foo; } print "\$foo was $foo\n"; }; $thr2 = async { $bar = 7; { lock ($a); # Block until we can get access to $a $c = $a; $a = $c * $bar; } print "\$bar was $bar\n"; }; $thr1->join; $thr2->join; print "\$a is $a\n";
lock() blocks the thread until the variable being locked is available. When lock() returns, your thread can be sure that no other thread can lock that variable until the innermost block containing the lock exits.
It's important to note that locks don't prevent access to the variable in question, only lock attempts. This is in keeping with Perl's longstanding tradition of courteous programming, and the advisory file locking that flock() gives you. Locked subroutines behave differently, however. We'll cover that later in the article.
You may lock arrays and hashes as well as scalars. Locking an array, though, will not block subsequent locks on array elements, just lock attempts on the array itself.
Finally, locks are recursive, which means it's okay for a thread to lock a variable more than once. The lock will last until the outermost lock() on the variable goes out of scope.
Thread Pitfall: Deadlocks
Locks are a handy tool to synchronize access to data. Using them properly is the key to safe shared data. Unfortunately, locks aren't without their dangers. Consider the following code:
use Thread qw(async yield); $a = 4; $b = "foo"; async { lock($a); yield; sleep 20; lock ($b); }; async { lock($b); yield; sleep 20; lock ($a); };
This program will probably hang until you kill it. The only way it won't hang is if one of the two async() routines acquires both locks first. A guaranteed-to-hang version is more complicated, but the principle is the same.
The first thread spawned by async() will grab a lock on $a then, a second or two later, try to grab a lock on $b. Meanwhile, the second thread grabs a lock on $b, then later tries to grab a lock on $a. The second lock attempt for both threads will block, each waiting for the other to release its lock.
This condition is called a deadlock, and it occurs whenever two or more threads are trying to get locks on resources that the others own. Each thread will block, waiting for the other to release a lock on a resource. That never happens, though, since the thread with the resource is itself waiting for a lock to be released.
There are a number of ways to handle this sort of problem. The best way is to always have all threads acquire locks in the exact same order. If, for example, you lock variables $a, $b, and $c, always lock $a before $b, and $b before $c. It's also best to hold on to locks for as short a period of time to minimize the risks of deadlock.
Queues: Passing Data Around
A queue is a special thread-safe object that lets you put data in one end and take it out the other without having to worry about synchronization issues. They're pretty straightforward, and look like this:
use Thread qw(async); use Thread::Queue; my $DataQueue = Thread::Queue->new(); $thr = async { while ($DataElement = $DataQueue->dequeue) { print "Popped $DataElement off the queue\n"; } }; $DataQueue->enqueue(12); $DataQueue->enqueue("A", "B", "C"); sleep 10; $DataQueue->enqueue(undef);
You create the queue with "Thread::Queue->new". Then you can add lists of scalars onto the end with enqueue(), and pop scalars off the front of it with dequeue(). A queue has no fixed size, and can grow as needed to hold everything pushed on to it.
If a queue is empty, dequeue() blocks until another thread enqueues something. This makes queues ideal for event loops and other communications between threads.
Threads And Code
In addition to providing thread-safe access to data via locks and queues, threaded Perl also provides general-purpose semaphores for coarser synchronization than locks provide and thread-safe access to entire subroutines.Semaphores: Synchronizing Data Access
Semaphores are a kind of generic locking mechanism. Unlike lock, which gets a lock on a particular scalar, Perl doesn't associate any particular thing with a semaphore so you can use them to control access to anything you like. In addition, semaphores can allow more than one thread to access a resource at once, though by default semaphores only allow one thread access at a time.- Basic semaphores
-
Semaphores have two methods, down and up. down decrements the resource
count, while up increments it. down calls will block if the
semaphore's current count would decrement below zero. This program
gives a quick demonstration:
use Thread qw(yield); use Thread::Semaphore; my $semaphore = Thread::Semaphore->new(); $GlobalVariable = 0; $thr1 = Thread->new( \&sample_sub, 1 ); $thr2 = Thread->new( \&sample_sub, 2 ); $thr3 = Thread->new( \&sample_sub, 3 ); sub sample_sub { my $SubNumber = shift @_; my $TryCount = 10; my $LocalCopy; sleep 1; while ($TryCount--) { $semaphore->down; $LocalCopy = $GlobalVariable; print "$TryCount tries left for sub $SubNumber (\$GlobalVariable is $GlobalVariable)\n"; yield; sleep 2; $LocalCopy++; $GlobalVariable = $LocalCopy; $semaphore->up; } }
The three invocations of the subroutine all operate in sync. The semaphore, though, makes sure that only one thread is accessing the global variable at once.
- Advanced Semaphores
-
By default, semaphores behave like locks, letting only one thread
down() them at a time. However, there are other uses for semaphores.
Each semaphore has a counter attached to it. down() decrements the counter and up() increments the counter. By default, semaphores are created with the counter set to one, down() decrements by one, and up() increments by one. If down() attempts to decrement the counter below zero, it blocks until the counter is large enough. Note that while a semaphore can be created with a starting count of zero, any up() or down() always changes the counter by at least one. $semaphore->down(0) is the same as $semaphore->down(1).
The question, of course, is why would you do something like this? Why create a semaphore with a starting count that's not one, or why decrement/increment it by more than one? The answer is resource availability. Many resources that you want to manage access for can be safely used by more than one thread at once.
For example, let's take a GUI driven program. It has a semaphore that it uses to synchronize access to the display, so only one thread is ever drawing at once. Handy, but of course you don't want any thread to start drawing until things are properly set up. In this case, you can create a semaphore with a counter set to zero, and up it when things are ready for drawing.
Semaphores with counters greater than one are also useful for establishing quotas. Say, for example, that you have a number of threads that can do I/O at once. You don't want all the threads reading or writing at once though, since that can potentially swamp your I/O channels, or deplete your process' quota of filehandles. You can use a semaphore initialized to the number of concurrent I/O requests (or open files) that you want at any one time, and have your threads quietly block and unblock themselves.
Larger increments or decrements are handy in those cases where a thread needs to check out or return a number of resources at once.
Attributes: Restricting Access To Subroutines
In addition to synchronizing access to data or resources, you might find it useful to synchronize access to subroutines. You may be accessing a singular machine resource (perhaps a vector processor), or find it easier to serialize calls to a particular subroutine than to have a set of locks and semaphores.One of the additions to Perl 5.005 is subroutine attributes. The Thread package uses these to provide several flavors of serialization. It's important to remember that these attributes are used in the compilation phase of your program so you can't change a subroutine's behavior while your program is actually running.
Subroutine Locks
The basic subroutine lock looks like this:
sub test_sub :locked { }
This ensures that only one thread will be executing this subroutine at any one time. Once a thread calls this subroutine, any other thread that calls it will block until the thread in the subroutine exits it. A more elaborate example looks like this:
use Thread qw(yield); Thread->new(\&thread_sub, 1); Thread->new(\&thread_sub, 2); Thread->new(\&thread_sub, 3); Thread->new(\&thread_sub, 4); sub sync_sub :locked { my $CallingThread = shift @_; print "In sync_sub for thread $CallingThread\n"; yield; sleep 3; print "Leaving sync_sub for thread $CallingThread\n"; } sub thread_sub { my $ThreadID = shift @_; print "Thread $ThreadID calling sync_sub\n"; sync_sub($ThreadID); print "$ThreadID is done with sync_sub\n"; }
The "locked" attribute tells perl to lock sync_sub(), and if you run this, you can see that only one thread is in it at any one time.
Methods
Locking an entire subroutine can sometimes be overkill, especially when dealing with Perl objects. When calling a method for an object, for example, you want to serialize calls to a method, so that only one thread will be in the subroutine for a particular object, but threads calling that subroutine for a different object aren't blocked. The method attribute indicates whether the subroutine is really a method.
use Thread; sub tester { my $thrnum = shift @_; my $bar = Foo->new(); foreach (1..10) { print "$thrnum calling per_object\n"; $bar->per_object($thrnum); print "$thrnum out of per_object\n"; yield; print "$thrnum calling one_at_a_time\n"; $bar->one_at_a_time($thrnum); print "$thrnum out of one_at_a_time\n"; yield; } } foreach my $thrnum (1..10) { Thread->new(\&tester, $thrnum); } package Foo; sub new { my $class = shift @_; return bless [@_], $class; } sub per_object :locked :method { my ($class, $thrnum) = @_; print "In per_object for thread $thrnum\n"; yield; sleep 2; print "Exiting per_object for thread $thrnum\n"; } sub one_at_a_time :locked { my ($class, $thrnum) = @_; print "In one_at_a_time for thread $thrnum\n"; yield; sleep 2; print "Exiting one_at_a_time for thread $thrnum\n"; }
As you can see from the output (omitted for brevity; it's 800 lines) all the threads can be in per_object() simultaneously, but only one thread is ever in one_at_a_time() at once.
Locking A Subroutine
You can lock a subroutine as you would lock a variable. Subroutine locks work the same as specifying a "locked" attribute for the subroutine, and block all access to the subroutine for other threads until the lock goes out of scope. When the subroutine isn't locked, any number of threads can be in it at once, and getting a lock on a subroutine doesn't affect threads already in the subroutine. Getting a lock on a subroutine looks like this:
lock(\&sub_to_lock);
Simple enough. Unlike the "locked" attribute, which is a compile time option, locking and unlocking a subroutine can be done at runtime at your discretion. There is some runtime penalty to using lock(\&sub) instead of the "locked" attribute, so make sure you're choosing the proper method to do the locking.
You'd choose lock(\&sub) when writing modules and code to run on both threaded and unthreaded Perl, especially for code that will run on 5.004 or earlier Perls. In that case, it's useful to have subroutines that should be serialized lock themselves if they're running threaded, like so:
package Foo; use Config; $Running_Threaded = 0; BEGIN { $Running_Threaded = $Config{'usethreads'} } sub sub1 { lock(\&sub1) if $Running_Threaded }
This way you can ensure single-threadedness regardless of which version of Perl you're running.
General Thread Utility Routines
We've covered the workhorse parts of Perl's threading package, and with these tools you should be well on your way to writing threaded code and packages. There are a few useful little pieces that didn't really fit in anyplace else.What Thread Am I In?
The Thread->self method provides your program with a way to get an object representing the thread it's currently in. You can use this object in the same way as the ones returned from the thread creation.Thread IDs
tid() is a thread object method that returns the thread ID of the thread the object represents. Thread IDs are integers, with the main thread in a program being 0. Currently Perl assigns a unique tid to every thread ever created in your program, assigning the first thread to be created a tid of 1, and increasing the tid by 1 for each new thread that's created.Are These Threads The Same?
The equal() method takes two thread objects and returns true if the objects represent the same thread, and false if they don't.What Threads Are Running?
Thread->list returns a list of thread objects, one for each thread that's currently running. Handy for a number of things, including cleaning up at the end of your program:
# Loop through all the threads foreach $thr (Thread->list) { # Don't join the main thread or ourselves if ($thr->tid && !Thread::equal($thr, Thread->self)) { $thr->join; } }
The example above is just for illustration. It isn't strictly necessary to join all the threads you create, since Perl detaches all the threads before it exits.
A Complete Example
Confused yet? It's time for an example program to show some of the things we've covered. This program finds prime numbers using threads.
1 #!/usr/bin/perl -w 2 # prime-pthread, courtesy of Tom Christiansen 3 4 use strict; 5 6 use Thread; 7 use Thread::Queue; 8 9 my $stream = Thread::Queue->new(); 10 my $kid = Thread->new(\&check_num, $stream, 2); 11 12 for my $i ( 3 .. 1000 ) { 13 $stream->enqueue($i); 14 } 15 16 $stream->enqueue(undef); 17 $kid->join(); 18 19 sub check_num { 20 my ($upstream, $cur_prime) = @_; 21 my $kid; 22 my $downstream = Thread::Queue->new(); 23 while (my $num = $upstream->dequeue) { 24 next unless $num % $cur_prime; 25 if ($kid) { 26 $downstream->enqueue($num); 27 } else { 28 print "Found prime $num\n"; 29 $kid = Thread->new(\&check_num, $downstream, $num); 30 } 31 } 32 $downstream->enqueue(undef) if $kid; 33 $kid->join() if $kid; 34 }
This program uses the pipeline model to generate prime numbers. Each thread in the pipeline has an input queue that feeds numbers to be checked, a prime number that it's responsible for, and an output queue that it funnels numbers that have failed the check into. If the thread has a number that's failed its check and there's no child thread, then the thread must have found a new prime number. In that case, a new child thread is created for that prime and stuck on the end of the pipeline.
This probably sounds a bit more confusing than it really is, so lets go through this program piece by piece and see what it does. (For those of you who might be trying to remember exactly what a prime number is, it's a number that's only evenly divisible by itself and 1)
The bulk of the work is done by the check_num() subroutine, which takes a reference to its input queue and a prime number that it's responsible for. After pulling in the input queue and the prime that the subroutine's checking (line 20), we create a new queue (line 22) and reserve a scalar for the thread that we're likely to create later (line 21).
The while loop from lines 23 to line 31 grabs a scalar off the input queue and checks against the prime this thread is responsible for. Line 24 checks to see if there's a remainder when we modulo the number to be checked against our prime. If there is one, the number must not be evenly divisible by our prime, so we need to either pass it on to the next thread if we've created one (line 26) or create a new thread if we haven't.
The new thread creation is line 29. We pass on to it a reference to the queue we've created, and the prime number we've found.
Finally, once the loop terminates (because we got a 0 or undef in the queue, which serves as a note to die), we pass on the notice to our child and wait for it to exit if we've created a child (Lines 32 and 37).
Meanwhile, back in the main thread, we create a queue (line 9) and the initial child thread (line 10), and pre-seed it with the first prime: 2. Then we queue all the numbers from 3 to 1000 for checking (lines 12-14), then queue a die notice (line 16) and wait for the first child thread to terminate (line 17). Because a child won't die until its child has died, we know that we're done once we return from the join.
That's how it works. It's pretty simple; as with many Perl programs, the explanation is much longer than the program.
Conclusion
A complete thread tutorial could fill a book (and has, many times), but this should get you well on your way. The final authority on how Perl's threads behave is the documentation bundled with the Perl distribution, but with what we've covered in this article, you should be well on your way to becoming a threaded Perl expert.Bibliography
Here's a short bibliography courtesy of JA~Xrgen Christoffel:Introductory Texts
Birrell, Andrew D. An Introduction to Programming with Threads. Digital Equipment Corporation, 1989, DEC-SRC Research Report #35 online as http://www.research.digital.com/SRC/staff/birrell/bib.html (highly recommended)Robbins, Kay. A., and Steven Robbins. Practical Unix Programming: A Guide to Concurrency, Communication, and Multithreading. Prentice-Hall, 1996.
Lewis, Bill, and Daniel J. Berg. Multithreaded Programming with Pthreads. Prentice Hall, 1997, ISBN 0-13-443698-9 (a well-written introduction to threads).
Nelson, Greg (editor). Systems Programming with Modula-3. Prentice Hall, 1991, ISBN 0-13-590464-1.
Nichols, Bradford, Dick Buttlar, and Jacqueline Proulx Farrell. Pthreads Programming. O'Reilly & Associates, 1996, ISBN 156592-115-1 (covers POSIX threads).
OS-Related References
Boykin, Joseph, David Kirschen, Alan Langerman, and Susan LoVerso. Programming under Mach. Addison-Wesley, 1994, ISBN 0-201-52739-1.Tanenbaum, Andrew S. Distributed Operating Systems. Prentice Hall, 1995, ISBN 0-13-219908-4 (great textbook).
Silberschatz, Abraham, and Peter B. Galvin. Operating System Concepts, 4th ed. Addison-Wesley, 1995, ISBN 0-201-59292-4
Other References
Arnold, Ken and James Gosling. The Java Programming Language, 2nd ed. Addison-Wesley, 1998, ISBN 0-201-31006-6.Le Sergent, T. and B. Berthomieu. ``Incremental MultiThreaded Garbage Collection on Virtually Shared Memory Architectures'' in Memory Management: Proc. of the International Workshop IWMM 92, St. Malo, France, September 1992, Yves Bekkers and Jacques Cohen, eds. Springer, 1992, ISBN 3540-55940-X (real-life thread applications).
Acknowledgements
Thanks (in no particular order) to Chaim Frenkel, Steve Fink, Gurusamy Sarathy, Ilya Zakharevich, Benjamin Sugars, JA~Xrgen Christoffel, Joshua Pritikin, and Alan Burlison, for their help in reality-checking and polishing this article. Big thanks to Tom Christiansen for his rewrite of the prime number generator.AUTHOR
Dan Sugalski<EMAIL_ADDRESS>This article originally appeared in The Perl Journal #10, and is copyright 1998 The Perl Journal. It appears courtesy of Jon Orwant and The Perl Journal. This document may be distributed under the same terms as Perl itself.
Index
- NAME
- DESCRIPTION
- What Is A Thread Anyway?
- Threaded Program Models
- Native threads
- What kind of threads are perl threads?
- Threadsafe Modules
- Thread Basics
- Threads And Data
- Threads And Code
- General Thread Utility Routines
- A Complete Example
- Conclusion
- Bibliography
- Acknowledgements
- AUTHOR
- Copyrights
This document was created by man2html, using the manual pages.
Time: 05:29:08 GMT, December 24, 2015


Methods
Instance Public methods
edit()
Link
Source: show
# File app/controllers/services_controller.rb, line 11 def edit @service = @project.gitlab_ci_service # Create if missing @service = @project.create_gitlab_ci_service unless @service end
index()
Link
Source: show
# File app/controllers/services_controller.rb, line 7 def index @gitlab_ci_service = @project.gitlab_ci_service end
test()
Link
Source: show
# File app/controllers/services_controller.rb, line 28 def test commits = project.commits(project.default_branch, nil, 3) data = project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{project.default_branch}", current_user) @service = project.gitlab_ci_service @service.execute(data) redirect_to :back end


shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext shoptext


$uiViewScroll
ui.router.state
When called with a jqLite element, it scrolls the element into view (after a
$timeout
so the DOM has time to refresh).
If you prefer to rely on $anchorScroll
to scroll the view to the anchor,
this can be enabled by calling $uiViewScrollProvider.useAnchorScroll()
.


Steyn, Miller, Morris released from IPL contracts
Cape Town - Proteas fast bowler Dale Steyn has been released from his Indian Premier League (IPL) contract by the Royal Challengers Bangalore for next year's 13th edition.
Steyn, who retired from Test cricket in August, only played two IPL matches this season after picking up a shoulder injury which resulted in him missing the Cricket World Cup in England.
In addition, Proteas all-rounder Chris Morris was dropped by the Delhi Capitals after picking up 13 wickets and scoring 32 runs in his nine matches in IPL 2019.
Hard-hitting batsman David Miller had a disappointing showing with the bat for the Kings XI Punjab, scoring 213 runs in 10 games, which saw his contract terminated.
Reigning champions, the Mumbai Indians, released Proteas fast bowler Beuran Hendricks, while they retained Proteas wicketkeeper/batsman Quinton de Kock.
The Chennai Super Kings retained Proteas star trio Imran Tahir, Faf du Plessis and Lungi Ngidi after their impressive seasons with the runners-up.
The IPL's highest wicket-taker last season, Kagiso Rabada, was retained by the Delhi Capitals after the Proteas fast bowler picked up 25 wickets in his 12 matches.
India's favourite South African, AB de Villiers, was retained by Royal Challengers Bangalore, which has been his IPL franchise since 2011.
Proteas fast bowler Hardus Viljoen was retained by the Kings XI Punjab side after taking seven wickets in his six matches this season.
Viljoen, who recently ended his Kolpak contract with Derbyshire, has played one Test for the Proteas in 2016.
The IPL 2020 player auction will take place in Kolkata on Thursday, December 19, 2019.
South African players retained:
Kagiso Rabada - Delhi Capitals
AB de Villiers - Royal Challengers Bangalore
Imran Tahir - Chennai Super Kings
Quinton de Kock - Mumbai Indians
Faf du Plessis - Chennai Super Kings
Lungi Ngidi - Chennai Super Kings
Hardus Viljoen - Kings XI Punjab
South African players released:
David Miller - Kings XI Punjab
Dale Steyn - Royal Challengers Bangalore
Chris Morris - Delhi Capitals
Beuran Hendricks - Mumbai Indians
Colin Ingram - Delhi Capitals
Anrich Nortje - Kolkata Knights Riders
Heinrich Klaasen - Royal Challengers Bangalore
- Compiled by Lynn Butler