text:
- Code Commit - http://www.codecommit.com/blog -
Software Transactional Memory in Scala
Posted By Daniel Spiewak On October 6, 2008 @ 12:00 am In Scala | 20 Comments
The fact is that there are a lot of problems that are hard to solve in a purely-functional style. That's not to say that no solution exists, but certain problems are very difficult to model without shared state. In such situations, a slightly different approach to concurrency must be considered. Actors are inapplicable, seeing as they are the embodiment of "shared-nothing" continuation passing, and fork/join [1] doesn't really help us. Usually, when faced with the need for shared mutable state, most developers will resort to the old-fashioned technique of locking everything and controlling access to that state one thread at a time. The solution often goes something like this:
public class Container { private int value; private final ReadWriteLock lock = new ReentrantReadWriteLock(); public int getValue() { lock.readLock().lock(); try { return value; } finally { lock.readLock.unlock(); } } public void setValue(int value) { lock.writeLock().lock(); try { this.value = value; } finally { lock.writeLock.unlock(); } } }
Obviously, most scenarios which call for such locking are a bit more complex, but you get the picture. There are two very serious problems with locking:
The first issue is obvious: there is nothing actually preventing us from accessing
value without locking. What's worse, it would be just as easy to lock, access
value and then forget to unlock when we were done. There is no logical connection between
value and its lock, the implementation rules are solely enforced by convention. Of course, we can avoid the problem of forgetting to unlock by using a locking strategy which is lexical in nature, but in that case our second issue (throughput) becomes even more pronounced:
private int value; private final Object lock = new Object(); public int getValue() { synchronized (lock) { return value; } } public void setValue(int value) { synchronized (lock) { this.value = value; } }
The problem here is that everything blocks everything else. If one thread wants to retrieve value, it literally stops the world while the other threads wait their turn. Data integrity is guaranteed, but this was accomplished only by creating a serial bottleneck on read/write access to value. On top of that, we still have no enforced correlation between the lock and its corresponding piece of data.
What we have been doing here is called "pessimistic locking". We have literally started with the assumption that we are going to run into data contention issues. Our entire locking mechanism is designed with the worst case scenario in-mind: lots of threads trying to write to the same piece of data simultaneously. However, not every concurrent system is going to have constant interference between threads. As it turns out, in practice data contention is the exception rather than the rule. Given this, it would be very nice if we could design a system which gave threads the "benefit of the doubt", assuming that they will not conflict, while still somehow maintaining data integrity.
The answer to this is "optimistic locking". We turn the problem completely on its head. Instead of assuming that there will be problems and so locking everything preemptively, we assume that everything will be fine and just allow everyone free, non-blocking access. Of course, an "open-door policy" with regards to shared mutable state isn't enough in and of itself, we have to have some rule for dealing with contention issues, and some way of detecting those conflicts when they happen. Enter transactions…
The idea behind a purely-optimistic transactional memory model is that all write operations must occur within a transaction. Data can be read any time, but the memory model will ensure that the data is never in an "intermediate state" – or between writes. Let's consider the more complicated scenario of the transfer of funds from one bank account to another. The steps are as follows:
Of course, this isn't really an algorithm, it's a high-level overview. We're really looking at something a bit more complicated than it would seem:
def transfer(amount: Int, a: Account, b: Account) { a.balance = a.balance - amount b.balance = b.balance + amount }
I avoided using the
+= and
-= operators so as to illustrate the problem more explicitly. This operation has four separate operations on shared mutable state (the account balance). It's not too difficult to see how this could go terribly wrong in the case where two separate transfers are taking place simultaneously. For example, we could transfer $500 from account A into account B, while at the same time we transfer $200 from account B into account C. Remember, we're not locking anything, so we run the danger that our concurrent execution order will be interleaved in the following fashion:
[Thread1] Get balance of account A
[Thread1] Set balance of account A to its former amount less 500
[Thread1] Get balance of account B
[Thread2] Get balance of account B
[Thread1] Set balance of account B to its former amount plus 500
[Thread2] Set balance of account B to its former amount less 200
[Thread2] Get balance of account C
[Thread2] Set balance of account C to its former amount plus 200
The operation in red is the one we need to be concerned about.
Thread2 retrieved the balance of account B just prior to when it was modified by
Thread1. This means that when
Thread2 calculates the new balance (less 200), it will be basing its result on a now-obsolete balance. When it sets the balance, the $500 that was transferred from account A will mysteriously vanish, the unfortunate victim of a common race condition.
In a transactional system, both transfers would be separately handled in their own transaction. Neither of them would modify the other's data until all operations are completed, at which point the transaction would commit and the data would become "live". Thus, when the
Thread1 adds $500 to account B, the actual balance of account B will remain constant at its original value (prior to the transaction). Once the transaction commits, both the balance of A and B will be updated essentially simultaneously. There will never be a point where $500 is discovered missing "in transit" between two accounts.
This is only half the equation though. The real genius of the transactional model is just prior to committing, a transaction validates itself, ensuring that all of the data it worked with is still in the same state it was at the beginning of the transaction. If something has changed, then the transaction is invalidated and must be re-run automatically. Our issue from above can never happen because the
Thread2 transaction will attempt to validate itself, only to discover that the balance of account B has been changed in the meantime. Rather than yield to the race condition, the
Thread2 transaction will throw away its work and start from scratch. Assuming that nothing else is running, the second validation will be successful (since nothing will have changed concurrently) and the transaction will commit.
It all sounds much more complicated than it actually is. People familiar with modern databases like Oracle should already be comfortable working with optimistic transactional models. The technique is a little less common in software, but it can still be applied.
In order to make this work in a conventional application setting, we need to introduce a few more abstractions. There are several ways to go about this, but I have chosen to follow the model laid down by Rich Hickey in his implementation of Clojure's STM. In turn, Clojure seems to take a fair bit of inspiration from Haskell's STM monad, although it does not port over concepts like transaction composition and what Simon Payton Jones calls "choice". Basically, the design can be distilled as follows:
With all that in mind, let's get to work on an implementation!
Since these are the primitive building blocks of our STM, it seems logical that we should start here. At an extremely basic level, we will need a structure which looks something like the following:
class Ref[T](private var value: T) { def get = value def :=(value: T) { this.value = value } }
This is the basic idea anyway. We want to be able to retrieve a value from a reference using
get, and we want to be able to store a value in the reference using the
:= operator (hat tip to all of you rabid Pascal fan-boys). Unfortunately, we haven't really accomplished anything here. Yes, we have a reference to wrap around a mutable piece of data, but there are no associated concurrency semantics. Remember the definition of a reference? We must only be able to write to it within a transaction. Furthermore, the value returned from a reference within a transaction is not necessarily its current, world-visible state, but rather the data it had the moment the transaction began.
In order to accommodate these requirements, we will introduce the concept of a context. Both read and write access to a reference will require a context to be present. We will have one context for the entirety of world-visible state. Additionally, each transaction will have its own context. In that way, we can ensure that transaction modifications are kept local to itself prior to commit while at the same time preventing changes from other transactions from becoming visible after the transaction has started (potentially leading to data integrity problems). Our API has now evolved to something more like the following:
class Ref[T](private var value: T) { // ??? def get(c: Context) = c.retrieve(this) def :=(value: T)(c: Context) { c.store(this)(value) } }
I left the constructor undefined because of the fairly obvious problem in this implementation: how does the
Context get the values in the first place? For the moment, let's put that problem aside and deal with a more interesting one: limiting write access to within transactions. Recall that we're going to have two different kinds of contexts: a live context which is global, as well as a context which is local to the transaction. The requirement alone implies a way to statically restrict reference mutability to within transactions: require a type of context other than the live one. To this end, we will derive the following closed hierarchy. It is closed because there will be no other
Context implementations, preventing over-zealous API extensions from fouling up our semantics.
We will define
Context to be an abstract class and
LiveContext to be a singleton object. Each transaction will have its own
Transaction context which it will use in both read and write operations.
LiveContext will only be used outside of a transaction, when there is no other context available. To enforce this, we will restrict the type of the
Context taken by the reference assignment operator to only accept
def :=(value: T)(c: Transaction) { c.store(this)(value) }
With this in mind, we can start to envision what the syntax for reference operations will look like:
def transfer(amount: Int, a: Ref[Int], b: Ref[Int])(c: Transaction) { a.:=(a.get(c) - amount)(c) b.:=(b.get(c) + amount)(c) } // ... val accountA = new Ref[Int](1500) val accountB = new Ref[Int](200) // somehow call `transfer` as a transaction println("Account A: " + accountA.get(LiveContext)) println("Account B: " + accountB.get(LiveContext))
And just when our design was looking so nice too. We've succeeded in preventing at compile time the modification of references outside of transactions, but we did it at the cost of a tyrannical syntax. Fortunately, Scala has a handy mechanism for cleaning up syntax such as this, one which should reduce the volume of annoying bulk by several orders of magnitude: implicits.
IScala makes it possible to mark parameters as accepting implicit values. These parameters in turn become implicit values themselves. When a method which accepts an implicit parameter of a specific type is called with an implicit value of the same type in scope, the parameter can be omitted entirely. Thus, by marking
LiveContext as an implicit object and appropriately annotating the last parameter of
transfer as well as the
Context parameters of
Ref's accessor and mutator, we can eliminate almost all of the annoying bulk in the above example:
implicit object LiveContext extends Context { ... } class Ref[T](value: T) { // ??? def get(implicit c: Context) = c.retrieve(this) def :=(value: T)(implicit c: Transfer) { c.store(this)(value) } }
With these extra modifiers in place, we can redo our transfer snippet to see how things look. To cut down on line length, we will also assume that
accountA and
accountB are references in some sort of global scope:
val accountA = new Ref[Int](1500) val accountB = new Ref[Int](200) def transfer(amount: Int)(implicit t: Transaction) { accountA := accountA.get - amount accountB := accountB.get + amount } // somehow call `transfer` as a transaction println("Account A: " + accountA.get) println("Account B: " + accountB.get)
Pretty slick, and we aren't even finished yet! We can add an implicit conversion from
Ref[T] to
T, eliminating the need to call
get anywhere in the code:
implicit def refToValue[T](ref: Ref[T])(implicit c: Context) = { ref.get(c) }
…and the final example syntax:
val accountA = new Ref[Int](1500) val accountB = new Ref[Int](200) def transfer(amount: Int)(implicit t: Transaction) { accountA := accountA - amount accountB := accountB + amount } // somehow call `transfer` as a transaction println("Account A: " + accountA) println("Account B: " + accountB)
With the exception of the
:= syntax (which is unfortunately unavoidable), you would never be able to tell that references are being used rather than conventional vars. Even better, we have managed to preserve our static assurance that no reference may be modified outside of a transaction. If we were to attempt to call the
:= method without an instance of
Transaction on-hand, the Scala type checker would complain and our code would not compile. The we need to do to close the loop is to make sure that the only place a
Transaction instance can be obtained is inside a transaction (seems logical).
For the moment, let's shelve all of the implementation requirements for the STM and instead focus on the API. We already have an almost elegant syntax for references, but we're still missing one final piece: initiating the transaction. Being incredibly imaginative and innately creative, I decided the best way to devise an API for this would be to hit Wikipedia. After all, why come up with something original when someone smarter has already solved the problem?
// Insert a node into a doubly-linked list atomically atomic { newNode->prev = node; newNode->next = node->next; node->next->prev = newNode; node->next = newNode; } atomic (queueSize > 0) { remove item from queue and use it }
Credit: Software transactional memory # Proposed language support [2]
It's a fairly straightforward API, one which could be expressed in Scala as it stands if we really wanted to. Obviously the body of the first transaction is a little closer to C than Scala, but we can just take that as example pseudo-code and move on. The real core of the API is a single method,
atomic, which takes a function value and executes that function as a transaction. If a conditional is provided, it acts as a guard. If the guard ever returns
false, the transaction aborts and is not retried.
The only problem here is we haven't accounted for our implicit
Transaction parameter. Intuitively, we could just add a parameter of type
Transaction to the function value, but unfortunately Scala doesn't allow anonymous functions with implicit parameters. That leaves one of two options: either take the
Transaction as a parameter to the anonymous function and then store it in an implicit value within the function; or pass an actual method which takes an implicit parameter. In truth, either approach will work, but for the remainder of the article I will use the method-passing approach, rather than the separate assignment within the anonymous method.
Altogether, our API in action looks something like this:
val accountA = new Ref[Int](1500) val accountB = new Ref[Int](200) def transfer(amount: Int)(implicit t: Transaction) { accountA := accountA - amount accountB := accountB + amount } atomic(transfer(500)(_)) // run transaction println("Account A: " + accountA) println("Account B: " + accountB)
Notice the extra
(_) syntax in the call to atomic. (thanks, Jesper [3]!) This is required because transfer accepts an implicit parameter. Without it, Scala doesn't know whether we mean to call the method using some implicit value in scope or if we want the function value itself.
Remember this API. We'll come back to the implementation of this method after we have completed the rest of the framework. For now, let's move onto context…
Returning to the dark and mysterious internals of the implementation, we now come to the deep morass of
Context. As it turns out, everything in the STM will revolve around this class and its two separate implementations. Recall that it is responsible for retrieving reference values, controlling what data is visible from within a transaction and what data is live. Generally speaking, we are going to have the following design with respect to where reference data is handled:
LiveContext, access the One True copy of the data.
Transaction, access the One True copy if and only if there is no transaction-local version. Once the reference has been read, cache the data and return that value from all future reads within the transaction. We're cheating a bit here since we aren't taking a snapshot of the world on transaction start, we're waiting for the first reference read. As long as we get our validation right, this should be ok.
Logically, this is a simple default operation clouded by a fairly substantive special case (within a transaction after the reference has been read or written once). To handle the special case, it only makes sense that we use a map from reference to the data to which it corresponds in that transaction. Remember that the data within a transaction may be a bit behind the live copy.
We could use another map for the general case, but we can make things even simpler than that. Rather than having a global map from reference to value, we can just store the live values within the
Ref objects themselves. They will still need to delegate to their context to retrieve and store that value, but the actual live version can be kept locally. This simplifies
LiveContext tremendously:
class Ref[T](private[stm] var value: T) { def get(implicit c: Context) = c.retrieve(this) def :=(value: T)(implicit t: Transaction) { t.store(this)(value) } } // ... sealed abstract class Context { def retrieve[T](ref: Ref[T]): T } implicit object LiveContext extends Context { def retrieve[T](ref: Ref[T]) = ref.value }
In this iteration, we have simplified
Context a little bit, seeing as it is never actually used for storage. Notice that all we need to do in
LiveContext is delegate right back to the reference. This may seem like a bit of superfluous indirection but it becomes absolutely essential once we start considering
import collection._ final class Transaction private[stm] () extends Context { private val world = mutable.Map[Ref[Any], Any]() def retrieve[T](ref: Ref[T]) = { val castRef = ref.asInstanceOf[Ref[Any]] if (!world.contains(castRef)) { world(castRef) = ref.value } world(castRef).asInstanceOf[T] } def store[T](ref: Ref[T])(value: T) { val castRef = ref.asInstanceOf[Ref[Any]] world(castRef) = value } }
This is the reason we needed to redirect through retrieve rather than just grabbing the value directly in
Ref. Within a transaction, any dereferencing will polymorphically come to an instance of this class. The mutable map, world, handles the transaction-local cache of all values once they have been accessed. Thus, the reference can change after we have looked at it (when another transaction commits) and it doesn't affect the values local to our transaction. This technique is exceedingly powerful and in no small part responsible for the higher throughput made possible by the transactional model.
Incidentally, it is worth noting that within a transaction, references are not thread safe. Thus, if you start a transaction and then start manipulating references concurrently within that same transaction, bad things will happen. This isn't really a problem though because transactions are always designed to be single-threaded from start to finish. They are used in multi-threaded situations, they do not use multiple threads.
Now that we have the basic nuts and bolts of our STM framework, we need to start considering how we are going to commit transactions. The process is two fold: first, we validate all references either read or written to by the transaction, checking for anything which may have changed in the interim; and second, we copy all new data from our transaction-local cache into the live references. For the sake of simplicity, we will only allow one transaction to commit at a time. We could do a little better, but this should work just fine for the experimental stuff.
Validation is a toughy, but the second commit step is fairly easy to satisfy: just loop through a set of all writes and copy the changes into the corresponding
Ref. The necessary changes are as follows:
final class Transaction private[stm] () extends Context { private val world = mutable.Map[Ref[Any], Any]() private val writes = mutable.Set[Ref[Any]]() ... def store[T](ref: Ref[T])(v: T) { val castRef = ref.asInstanceOf[Ref[Any]] world(castRef) = v writes += castRef } def commit() = { CommitLock.synchronized { // TODO validate for (ref <- writes) { ref.value = world(ref) } } true } } private[stm] object CommitLock
commit method returns a
Boolean value indicating whether or not the commit was successful. If a conflict was detected the method returns
false and (presumably) the transaction will be tried again. Since we aren't doing any validation just yet, we will always return
true. Note that we don't really have to lock anything related to the
Ref instances in order to write their data. It is possible for another thread to be reading data from these same references at precisely the same time as we are writing to them. However, primitive memory operations are atomic by definition, meaning that we don't need to worry about data integrity on the level of a reference value.
Validation is actually the most important part of the transaction commit process and quite possibly the most important facet of the entire STM concept. Without it, there is nothing to prevent data integrity from breaking down and causing problems. (remember that $500 we lost?) Unfortunately, our system doesn't quite have the chops yet to support any sort of transaction validation.
In order to validate a
Ref, we need to compare its state to the state it was in at the moment we read from it or wrote to it (meaning into the transaction-local cache). We can't just compare values, partially because equals isn't fast enough, but also because it doesn't provide a strong enough guarantee about whether or not data has changed. What we need is some value which we control which indicates deterministically the current state of a
Ref and which can be used later to determine if that state has changed. In short, we need a revision number:
class Ref[T](value: T) { private[stm] var contents = (value, 0) // init revision to 0 }
The revision numbers have to be controlled statically with thread-safety, so the best place for them should be in the
Transaction singleton.
Transaction (the companion object for
Transaction the
Context) also contains our implicit conversion as well as that enigmatic
atomic method that we still have yet to implement.
object Transaction { private var rev_ = 1 private val revLock = new AnyRef private def rev = revLock.synchronized { val back = rev_ rev_ += 1 back } ... }
Empowered by a revision increment system which is guaranteed to produce unique values for each invocation, we can expand upon our concept just a little bit. Each
Transaction will have a unique revision number associated with it (maintained within the
rev field). Assuming a transaction successfully commits, it will not only modify the value of the references in question but also their revision, which it will set to its own number.
This revision system can be used in validation of transaction commit. Whenever we read or write to a Ref for the first time, we will store its current revision number within the transaction. When it comes time to commit the transaction, we can loop over our revision map and compare with the actual revision of the reference in question. If all of the expected revisions match up with reality, the transaction checks out and we can go ahead and commit. Otherwise, we have to assume that a transaction operating concurrently modified a reference we used and committed after we started our own transaction. Once this is known, we can't simply commit over the other transaction's changes, throwing away all of that money. Our transaction must be retried from scratch.
Now that we know how to validate, we can finally look at a completed version of commit (and supporting cast):
final class Transaction private[stm] (val rev: Int) extends Context { private val world = mutable.Map[Ref[Any], Any]() private val writes = mutable.Set[Ref[Any]]() private val version = mutable.Map[Ref[Any], Int]() def retrieve[T](ref: Ref[T]) = { ... if (!world.contains(castRef)) { ... if (!version.contains(castRef)) { version(castRef) = castRef.contents._2 } } ... } def store[T](ref: Ref[T])(v: T) { ... if (!version.contains(castRef)) { version(castRef) = ref.contents._2 } ... } def commit() = { CommitLock.synchronized { val back = world.foldLeft(true) { (success, tuple) => val (ref, _) = tuple success && ref.contents._2 == version(ref) } if (back) { for (ref <- writes) { ref.contents = (world(ref), rev) } } back } } }
It's a lot of code, but all fairly straightforward. The validation simply bears out our intuition: checking the revisions initially retrieved from the references with their current values. Here again we are making use of the fact that memory access is atomic. We don't need to worry about a revision changing out of sync with a value because both of them are encapsulated by a 2-tuple within the
Ref itself. Meanwhile, the validation can be trusted because of the
CommitLock: we don't need to worry about another transaction committing between our validation and when we actually get around to saving our values.
I said we would come back to this, and here we are! We never did implement the
atomic method, which is a bit of a shame seeing as it is what is responsible for kicking off the entire transactional process. Not only that, but it creates the
Transaction instance, ensures that the transaction gets committed once it has finished and it retries if that commit fails. Set in code, it looks something like this:
def atomic[A](f: (Transaction)=>A): A = atomic(true)(f) def atomic[A](cond: =>Boolean)(f: (Transaction)=>A) = { def attemptTransact(): A = { if (cond) { val trans = new Transaction(rev) try { val result = f(trans) if (trans.commit()) result else attemptTransact() } catch { case _ => attemptTransact() // if exception, assume conflict and retry } } else null.asInstanceOf[A] } attemptTransact() }
The only weird thing here is the use of an internal function to control the transaction dispatch process. This is necessary because we need to emulate the pattern of a
while loop without losing the ability to capture a return value. This is the one minor feature of the transaction API that we have designed which I haven't already discussed: the ability to return a value from a transaction. Practically speaking, this isn't needed too often since the very purpose of a transaction is to modify references, but it is still a pattern worth keeping in hand.
You will notice that we have some generic catch-all exception handling going on here. Whenever a transaction throws an exception, we assume that it has failed and we try again. To be honest, I wrestled back and forth with this decision. After all, if a transaction comes across a
NullPointerException on its first try, it's not likely to do any better the second time around, or the third, or the fourth, or the… On the other hand, there is a remote but very real possibility that data can briefly get into an inconsistent state within a transaction. To understand how, consider the following abstract scenario:
Everything gets straightened out in the end due to the validation, but there is still this hairy moment within transaction B that we have to worry about. Within the transaction, we have some data from before transaction A committed, and some from afterward. Validation is never going to let this slip by, but while the transaction is still executing we can run into some fairly serious issues.
Imagine for example that reference B is changed in such a way that it throws an exception in transaction B unless it is paired with just the right value of reference A. Since we have an inconsistent pairing between references A and B within transaction B, we will get an exception caused directly by a breakdown in data integrity. Because this is a data integrity issue, we want this exception to trigger a redo in the transaction. However, we can't really predict such exceptions, so there's no way we can distinguish between a legitimate exception (which should be propagated outside the transaction) and a data integrity fault. In short, we're in trouble.
Given the way we designed the STM framework, I don't really see a nice, efficient way to avoid this problem. There are other approaches we could take which don't have this issue, but that would either require an entirely different implementation or a much smarter developer taking the lead. I would be interested to see how Clojure handles this case…
Now that we have this full STM framework, it might be interesting to put it to work. To that end, let's create a simple market simulation with three businesses and a hundred potential customers, each with their own accounts and separate balances. All of these entities will have their own thread operating on their behalf, making purchases, excepting refunds and keeping the Mafia off their back. Bear in mind that this is a truly concurrent simulation with full thread semantics. We're not going to use actors or anything like that to reduce the number of threads involved, everything will operate in true parallel.
To make things a little more interesting, we will also associate a 7.5 % fee with each transfer, paid to a separate account. Also, each transfer will be logged presumably for later review. To make everything fun, we will have one final thread which monitors the entire market, summing up every account and checking the total. The obvious concern is that some collision in access of the shared data will lead to the unexpected loss (or gain) of wealth. So long as the total market value remains constant, we can assume that shared state is being handled appropriately.
Let's start out by defining our accounts and basic structure. Bear in mind that
Account is a type alias (similar to a C-style typedef) for
Ref[Long], it is not a separate class.
object BankFrenzy { import Transaction._ type Account = Ref[Long] private val fees = new Account private val log: Ref[Vector[Transfer]] = new Ref(EmptyVector) def main(args: Array[String]) { val business1 = new Account(15000) val business2 = new Account(20000) val business3 = new Account(50000) val people = (0 until 100).foldLeft(Vector[Account]()) { (vec, i) => vec + new Account(1000) } } }
Remember that all data contained within a reference must be completely immutable, otherwise the STM framework cannot help you. If you can just change the underlying data within a reference at will, then transaction semantics are useless (since revision tracking breaks down). To that end, we will use my port of Clojure's persistent vector [4] to handle the transfer log; and just because it's fun, we will also use it to manage personal accounts.
Moving on, we should probably define some functions to operate on these accounts. Remember, they must take an implicit parameter of type Transaction, otherwise they will be prevented from modifying references.
def transfer(amount: Long, from: Account, to: Account)(implicit t: Transaction) { log := log + Transfer(amount, from, to) val less = Math.round(amount * 0.075) from := from - amount to := to + (amount - less) fees := fees + less } def sum(portfolio: Vector[Account])(implicit t: Transaction) = { portfolio.foldRight(0:Long) { _ + _ } }
One thing worthy of attention here is the
sum method: we aren't actually modifying any references in this method, so why bother putting it within a transaction? The answer is to enforce data integrity. We want to make sure that we see a truly consistent picture of the entire market, and the only way to be absolutely sure of that is to use the conceptual "snapshot of the world" maintained by a transactional log.
Also notice that the
sum method does not store its result within a reference, it actually returns a value. This is one of the neat features of our STM implementation: it allows transactions to return values just like functions. This dramatically reduces the boilerplate which would normally be required to get the result of a calculation from within a transaction.
With this infrastructure in place, we can go ahead and create all of the threads we're going to need for the simulation:
val market = people + business1 + business2 + business3 + fees var running = true val secActor = thread { while (running) { val total = atomic(sum(market)(_)) println("Market value: $" + total) sleep(10) } } val businessActor = thread { while (running) { atomic(transfer(250, business1, business2)(_)) // transfer rent sleep(200) } } val peopleActors = for { i <- 0 until people.length val p = people(i) } yield thread { atomic(transfer(50, p, business3)(_)) // payoff the mob atomic(transfer(i * 10, p, business1)(_)) // purchase from business1 atomic(transfer(i * 3, business2, p)(_)) // refund from business2 }
This is assuming that we have already defined a utility method,
thread, in the following fashion:
def thread(f: =>Unit) = new Thread { override def run() { f } }
Just one of the many little tricks made possible by the staggering power of Scala's syntax.
There isn't much worthy of attention within our simulation threads, it's just a lot of concurrent operations running against some shared state. If we wanted to really have some fun, we could add
println status messages to each thread, allowing us to try the simulation multiple times and watch the thread interleaving change from run to run. However, all we're really interested in with this simulation is the assurance that data integrity is maintained at all times. To see that, all we really need is to check the starting market value, the ending value and some period market auditing while the simulation is in progress:
println("Starting market value: $" + atomic(sum(market)(_))) businessActor.start() secActor.start() for (pa <- peopleActors) pa.start() for (pa <- peopleActors) pa.join() running = false businessActor.join() secActor.join() println("Total fees: $" + fees) println("Final market value: $" + atomic(sum(market)(_)))
If we compile and run the simulation, the output will look something like this (on a dual-core, 2 Ghz processor):
Starting market value: $185000 Market value: $185000 Market value: $185000 Market value: $185000 Total fees: $5258 Final market value: $185000
We could try the simulation a hundred times with different CPU loads and even on separate machines, the results will always be the same. While there may be a greater or lesser number of concurrent market audits during the simulation, the values retrieved each time will be the same. From this we can conclude one important fact: we have succeeded in designing an STM framework which preserves data integrity.
In simulations like this one with a high degree of contested data, STM may actually be slower than a traditional, fine-grained locking strategy. However, just think for a moment about trying to write this simulation using Java's
ReentrantReadWriteLock class. It would be nearly impossible to design such a system, let alone maintain it. There would always be the danger that we would accidentally get the locking in the wrong order, or forget to lock something before we access it. In short, such an effort would be extremely hazard prone, and far more verbose. Using our STM framework, the resulting code was clean and simple to understand. It's easy to see why techniques like this are really starting to catch on.
Hopefully this has been an informative and enjoyable foray into the world of transactional memory systems. I will retroactively apologize for any areas where my facts are in err; I'm certainly quite new to all of these concepts. As per usual, the library described in this article is available for download. I was a little lax on the testing side of life, so you may want to vet the library a little bit before you trust it unsupervised in your data center.
There are a number of interesting aspects to STM that I didn't cover in this article, such as
retry and the related function,
check (implemented in the framework). Also left completely untouched is the monadic operation
orElse which can be used to compose transactions in a "first try this, then try that on failure" sort of way.
STM is a very active research topic today with a lot of the brightest minds in the industry pondering ways to make it better. While it certainly doesn't solve all of the problems associated with concurrency, it does have the potential to simplify locking and produce better performance under some conditions. Definately a technology to watch as it develops!
Article printed from Code Commit: http://www.codecommit.com/blog
URL to article: http://www.codecommit.com/blog/scala/software-transactional-memory-in-scala
URLs in this post:
[1] fork/join: http://www.codecommit.com/blog/scala/higher-order-fork-join-operators
[2] Software transactional memory # Proposed language support: http://en.wikipedia.org/wiki/Software_transactional_memory#Proposed_language_support
[3] Jesper: http://jnordenberg.blogspot.com/
[4] port of Clojure's persistent vector: http://www.codecommit.com/blog/misc/implementing-persistent-vectors-in-scala/final/Vector.scala
[5] Download BankFrenzy.scala: http://www.codecommit.com/blog/misc/software-transactional-memory-in-scala/BankFrenzy.scala
[6] Download scala_stm full sources: http://www.codecommit.com/blog/misc/software-transactional-memory-in-scala/scala_stm.zip
Click here to print.
All content copyright © 2010 Daniel Spiewak. Distributed under Creative Commons.
All code (unless otherwise stated) is licensed under the BSD License.


text:
Calendar | Community
| Family & Friends in the Armed Forces
| Milestones
Community Action |
Humane Society | YMCA
Mount Pulaski Courthouse Festival a
dancing in the streets good time
Send a link to a friend
[July 03, 2014]
MOUNT PULASKI - The Mount Pulaski
Courthouse Foundation's third annual street festival may have
kicked-off Friday night under cloudy skies and few rain showers, but
that sure did not put a damper on the evening's activities.
The Prairie Land Dancers kicked-off the event at 5:30 p.m. and
squared danced in the rain to a variety of songs from country
classics to swing music.
In the background, the luring aroma of Hilltop Catering's grilled
brats and hotdogs filled the air.
Meanwhile folks meandered around from tent to tent checking out the
food and drinks available. The city of Mount Pulaski served pulled
pork BBQ sandwiches, while the American Legion served alcoholic and
non-alcoholic beverages.
As the rain began to fall a little harder following the performance
by the square dancers, street festival organizer Renee Martin
announced there would be a 30 minute rain delay to allow for the
weather to pass.
At 6:30 p.m. Courthouse Foundation president, Tom Martin, addressed
the crowd with opening remarks. He began by thanking the 2013-2014
Mount Pulaski Grade School third graders who raised $610 toward the
continued restoration of the courthouse. Martin also mentioned a
Christmas tree project that several of the businesses around town
supported had also brought in between $3000-$4000 in donations. On
behalf of the committee Martin expressed his appreciation for the
community support and urged visitors to visit the courthouse and not
only sign in as guests, but also vote for the art show finalists
which included first and third graders of MPGS.
Martin mentioned that $70,000 had been raised in the community in
recent years and this money goes toward the ongoing courthouse
projects such as cleaning, painting and repairing windows. He noted
that the state cannot do much these days and it's been left up to
the residents of Mount Pulaski to take over.
Martin also said a $250,000 donation has been bequeathed from the
Waldo Bertoni family. In closing, Martin thanked everyone who had
helped with the courthouse and said, "It's kinda up to the Mount
Pulaski folks to take care of it."
Following Martin's remarks, Abraham Lincoln impersonator Randy
Duncan addressed the crowd with stories of the past. He spoke as Mr.
Lincoln and talked of meeting Mary Todd at a dance back in the day
in Springfield. He explained how the men would stand in one corner
of the room and the women in the other corner and eventually a man
would work up the courage to ask a woman to dance. He finally did
just that, asking Mary Todd, "Ma'am, I should like to dance with you
in the worst way." She obliged and eventually returned to her
friends saying, "He danced with me in the worst way."
Mr. Lincoln also mentioned traveling the courthouse circuit and
meeting Judge Davis in Mount Pulaski . He noted how he would go on
to appoint Judge Davis, a good man, to the Supreme Court. He also
spoke of a court case he took on for five dollars in nearby
The crowd truly enjoyed hearing Abraham Lincoln speak, as the folks
of Mount Pulaski are very proud of the connection to him and to
their historic courthouse where Lincoln once practiced his
profession as a circuit rider lawyer.
Next up on the entertainment stage was a man who also has a more
recent historic connection to Mount Pulaski as well. And boy, did
the crowd ever enjoy this performer. John Schlitt, a native of Mount
Pulaski, former lead singer of the '70s rock group Head East, and
lead singer of the Christian rock group Petra, took the stage with a
lively introduction of himself and immediately launched into the
Head East classic "Since You've Been Gone." The crowd loved it! And
this was just the beginning of a night of mutual admiration between
John and his hometown friends and fans. Schlitt quickly noted that
even though he's been away from Mount Pulaski for a long time, "I am
always here in Mount Pulaski in spirit."
John also sang "The Grafting" from his solo release of the same
name. He also mixed things up a bit by performing "Take Me Home,"
"Faith and Freedom," "Hope That Saves The World" and "Trading My
[to top of second column]
Much to the delight of the crowd, John even performed the
Petra hit, "Beyond Belief." But it was this next song from the
1974 album "Flat As a Pancake" that had the crowd on it's feet
and singing to every word.
When the music began for "Never Been Any Reason," the hometown
folks knew they were in for a rare treat, and John delighted in
the experience as much as his fans. He even invited a young man
from the crowd by the name of Stephen Biker of Milan, MO to join
him on stage and sing this classic hit. What a priceless moment
that was for all who were on the Mount Pulaski square Friday
John Schlitt, the man whose career has spanned decades and taken
him to all 50 states and 35 countries performing in front of
millions of fans, was back in the community where it all began.
He was among friends and family. And he wasn't done yet.
Following "Never Been Any Reason" he asked the crowd if they
wanted one more. People were dancing in the street as John
closed his set appropriately with "Get Up and Enjoy Yourself."
Yes, John, the folks of Mount Pulaski did just that thanks to
Immediately after getting off stage, John was greeted with a
line of people who wished to express their sincere gratitude for
his wonderful performance and also share memories with him from
the good 'ole days. It was also a nice feeling to witness local
high school musicians Brady Walsh and Andrew Moody of the band
"Haircut Actual" standing in line to meet John, and of course,
take selfies.
John has influenced a whole new generation here in Mount
Pulaski. And as evidenced by the enthusiasm of the crowd, John
re-ignited a spark in that crowd that grew up with him and his
music 'back in the day.' What a treat for all the folks of Mount
The final musical performance of the evening was the band
"Rosetta Stone." Rosetta Stone performed a variety of country
and rock hits that kept the lively crowd going even a little
later than anticipated. Not to take anything away from Rosetta
Stone because they, too, were wonderful, but hometown boy John
Schlitt was a tough act to follow. Rosetta Stone however, rose
to the occasion and John Schlitt himself commented what a
"fantastic band they are" and he even told Renee Martin that "it
was a pleasure to share the stage with them." Renee Martin also
noted that "it is definitely a good possibility that we may
bring John back in the future. He is such a humble and down to
earth man. He enjoyed visiting the old friends, family and
When asked about plans for next year's street festival, Renee
Martin commented, "Next year I look forward to concentrating on
the things people liked the best and improving upon them. This
festival is based on the simplicity of things. We just try to
provide a simple, but fun night where folks can gather and
socialize. We like to bring awareness to the courthouse and
thank the volunteers and community for all they do throughout
the year."
Judging by the enthusiastic crowd Friday night, the evening
could truly be deemed a success. Kudos to all who put together a
such a nice event.
[By TEENA LOWERY]
Note: John Schlitt will be returning to Illinois in August.
He will be appearing with Petra at the Illinois State Fair on August
Back to top

subset: commoncrawl


text:
Views expressed here are solely that of my own. Please make sure that you test the code/queries that appear on my blog before applying them to the production environment.
Saturday, November 27, 2010
Oracle Database 11g R2: Interactive Quick Reference
Oracle has released "Interactive Quick Reference" for DBA's and Developer's to better understand Oracle Database architecture. It includes 1) List of DBA Views, 2) Database Architecture Diagram, and 3) List of all Database Background Processes by category. Click here to read more about it and click here to download it.
Posted by Asif Momen at 1:02 AM
Labels: Oracle 11g R2
No comments:
Subscribe to: Post Comments (Atom)


text:
|Our Lady of Cocharcas Under the Baldachin
|Double-Sided Diptych
How can art aid in the reconciliation of new and old beliefs?
Through trade, travel, conquest, and missionary zeal, Christianity has spread around the globe. Along the way, it has been adapted and interpreted according to the values, beliefs, and needs of various populations at different points in history. The art produced when Christianity has been adopted by or introduced to traditionally non-Christian cultures has both reflected the incorporation of foreign ideas and, at the same time, produced original ways of understanding those ideas. Images like Our Lady of Cocharcas or icon diptychs from Ethiopia show the fusion of old and new that has occurred when people have attempted to reconcile not only their indigenous religious beliefs with Christianity, but also their traditional art forms with those of European origin.back
Questions to Consider
- Both of these images depict the Virgin Mary. In what ways does each image adhere to traditional Christian-European models? How has each adapted those models to address the visual and cultural values of its audience?
- If you had to guess, would you attribute these works to foreign artists or artists native to Peru and Ethiopia respectively? Can you make a case for the reverse?
- Religious art, including the pieces shown here, has a spiritual function for devotees. In the context of cultural convergence and religious conversion, what other functions might images like these serve?


text:
Bushkill Falls, scheduled to open for the 2013 season today — weather permitting — will unveil some major changes for the second year in a row.
Bushkill Falls, scheduled to open for the 2013 season today — weather permitting — will unveil some major changes for the second year in a row.
Damage from Hurricane Sandy late October last year led to major changes in the 300-acre park.
"Nearly 50 trees needed to be removed from portions of the two-mile trail system," said Donna Smith, Bushkill Falls general manager. "Because of the destruction, we ended the 2012 season early in order to begin the removal and repair process. Anyone who has been to Bushkill Falls knows it's a challenge to get equipment onto the trails."
The Bridesmaid's Falls area experienced the greatest devastation, said Smith, as 12 trees had to be removed and a new 70-foot walkway on the red trail was completed. The green trail has repaired walkways and railings. Pictures of the project are posted on the Facebook page.
In August 2012 an $800,000 renovation to Bushkill Falls' food and beverage facility and gift and souvenir shops was completed. The "Servery" had state-of-the-art appliances installed, seating areas redesigned and expanded, a new deck built that increases outside seating availability and new menu items added.
The cafeteria-style layout allows diners to select their prepared to order items and smoothly head to the checkout. Menu items have been broadened and include freshly made salads, fresh fruit, burgers, hot dogs, the falls' own smoked pulled pork, sausage and peppers, kielbasa with sauerkraut and more.
Once the park season begins, gates are open every day at 9 a.m. through sometime in October or November, depending on the weather. General admission is $ 12.50, $11.50 age 62 and older, $7 ages 4-12, free age 3 and younger. Admission includes entrance to all exhibits. Parking is free.
For a calendar of events, seasonal closing times, directions and accommodations, visit visitbushkillfalls.com or call 570-588-6682.


text:
#138: Last-Minute Christmas Gift Idea
If you're scrambling around, trying to find the perfect gift for the pro football nut on your list, I have a suggestion.
I was recently provided a review copy of the following book, which may be the most comprehensive tome on the subject of the Super Bowl.
"The Ultimate Super Bowl Book" is as complete a history of professional sports' biggest annual event as you could ever hope to find (until Super Bowl XLIV is played this coming February...at which point I presume it will be amended).
Each chapter is presented mostly through the journalistic eye of author and long-time Green Bay Packers writer Bob McGinn with some occasion for editorializing. However, 99% of the book is "Just the facts, ma'am."
And facts there are.
Each of the 43 chapters (one for each of the Super Bowls played to date) describes each score in a page-turning narrative format (though often non-chronological), gives credit to those who made otherwise thankless blocks on key plays, and explains who made critical errors that cost their team points.
Those literary depictions alone would be worth the purchase price.
The true treasures, however, are the in-chapter tables that provide complete team and individual statistics, the rosters for both teams and all of the coaches. McGinn credits the compilation these tables to his wife. These tables elevate this piece of work from "enlightening" to "important".
In addition, the appendix at the end of the book reveals just about every current Super Bowl record, including what team gained the most total yards in a Super Bowl and which two teams combined for the most passing first downs. I'd reveal those facts myself, but I'd be giving things away.
McGinn also deftly interlaces quotations from coaches, players, and front office officials into his narratives. Some of those words were spoken shortly after the game in question was concluded. Others were said in interviews years later, giving the reader the added perspective of time and how some people on the losing end of the contests saw the game after the heat of the moment had long passed.
He also takes the time to compile a few "Top Ten" lists, including "Top Ten Hits", "Top Ten Plays by a Wide Receiver" and "Top Ten Super Bowl Upsets". Feel free to agree or disagree.
As someone who did not watch a Super Bowl until the Chicago Bears drubbed the New England Patriots in Super Bowl XX and didn't really understand the game until somewhere around XXIX, when the San Francisco 49ers proved they were more than a match for the San Diego Chargers, I found the accounts of the earlier Super Bowls extremely informative. For instance, perhaps the MVP of the New York Jets over the Baltimore Colts should have been running back Matt Snell (121 rushing yards on 30 attempts and the only touchdown for New York) against the vaunted Baltimore Colts defense.
The later Super Bowls (XXX through XLIII) were more like a refresher course, with the added insight of why some of the teams employed the offensive or defensive strategies they did, or why players ended up committing key mistakes.
Why did Pittsburgh Steelers quarterback Neil O'Donnell throw two balls into the stomach of the Dallas Cowboys' Larry Brown in Super Bowl XXX?
How were the Denver Broncos able to contain the explosive Brett Favre-led Green Bay Packers in Super Bowl XXXII?
Same for the New England Patriots against Kurt Warner and the St. Louis Rams' "Greatest Show on Turf" in XXXVI?
Finally, McGinn's work does not reflect any apparent bias, either on his part, or on the part of the media. While he mentions the New England Patriots' "Spygate" scandal, it is not until Chapter XLII, when they were defeated by the New York Giants. "Spygate" is not referenced in any of the teams' victories over St. Louis, Carolina, or Philadelphia. There is also no word from McGinn himself as to whether he thinks that gave New England an unfair advantage. He steers clear, offering only a quote from Hall of Fame coach Don Shula on the subject.
He recognizes the controversy surrounding Super Bowl XL's officiating, offering many quotes from Seattle Seahawks coach Mike Holmgren throughout the chapter, but otherwise accurately portrays the game as an unspectacular contest decided by three big plays by the Pittsburgh Steelers and questionable clock management and untimely injuries suffered by the Seahawks.
This is an inspired piece of work.
Now, to the admittedly picky criticisms.
This first gripe is really something I don't think could have been helped. There are just so many people involved in each game, literally over 100 total. Over the course of a chapter, many of the names become confusing, especially if you are not a follower of either of the teams involved. Sometimes I found myself reading a quote or a depiction of a play, then thinking, "Wait, who was 'Smith' again? I'm sure he was introduced earlier in the chapter, but after Jones and Kendall and Brady and Mack, I'm not sure I remember..."
It's almost certainly a casualty of the absolute saturation of info, but occasionally it does affect the flow of reading if you like to get all of the details straight.
The second "complaint" is that sometimes the chapters in general have an odd flow to them. As mentioned previously, most of the chapters do not proceed in chronological order. Often, they will focus on the most exciting or pivotal points of the game first (something the readers will be more likely to recognize, such as Pittsburgh Steelers wide receiver Santonio Holmes's fingertip catch and toetip drag to help his team take the lead for good in XLIII). Then, after focusing on the play itself or the drive that led up to the play, the narrative will bounce to another part of the game that made the pivotal play necessary.
I realize that to have given an introductory paragraph highlighting the dramatics, then immediately starting at the beginning of the game and working through to the end would have made for a very dry read. Still, trying to follow the plethora of surnames while striving to recognize the chronology can stir the brain a little much at times.
Again, I don't think this is something that could be fixed without damaging another equally (or more) important facet of the book. Nevertheless, it exists. I am sure that McGinn and the publisher, MVP Books, talked about these things throughout the process.
And, finally, this book is only available in softcover. Perhaps it is because the book will be somewhat outdated in a year's time (another Super Bowl will have been played). Still, I feel this first printing should have also been available in hardcover as more of a collector's item.
Considering the scope of this project, the relative brevity and precision of his game-by-game dissections, the mountains of statistics and the extensive bibliography, all in under 400 pages, the aforementioned critiques cannot take anything significant away from this work.
(Five out of Five Stars).
"The Ultimate Super Bowl Book" is available at most bookstores and online booksellers, or through MVPBooks.com.


text:
Jr. Bankston, Flanagan, Jimmy W., Morgan, Johnny W. | 11/11/2006 3:40:11 AM
News Release Distributed 12/10/2003
The fall harvest season is near its end for this year, but farm safety still needs to be on the minds of farmers and farm workers, according to agents and specialists with the LSU AgCenter.
U.S. Department of Labor statistics show thousands of farm workers are injured and hundreds more die each year in farming accidents.
LSU AgCenter safety specialist Dr. David Bankston said those who work in agriculture must remember there is danger and that being extremely alert and cautious are critical elements in avoiding accidents.
"When you're working around equipment as dangerous as this, you have to pay attention to what's going on and watch out for the people around you," Bankston said at a meeting earlier this year focused on stressing safety to farmers. "One of the most important things to remember in farm safety is to keep your cool."
Bankston said proper maintenance of equipment also is important, and he stressed making sure rollover protection structures are included on farm equipment – particularly tractors.
The Centers for Disease Control's census by region and age group for the years from 1986 through 1996 shows that the South leads the nation in fatal farm injuries from the age group less than 20 years of age. The southern region recorded 863 fatal farm injuries during that time frame, followed by the Midwest with 844.
The causes of fatal farm injuries for this age group during that period were led by 773, or 35.6 percent, caused by machinery. Another 585, or 26.9 percent, were the result of drowning.
The CDC report states that progress in the reduction of farm injuries and fatalities is attributed to more widespread use of rollover protection structures, also known as ROPS, improved emergency care in rural areas, certification of youth 14-15 years of age in the operation of farm machinery and general educational efforts toward farm safety.
But safety experts say it's important to note that not all tractor cabs actually qualify as rollover protection structures. The National Farm Medicine Center stresses that many older cabs don't provide rollover protection and that some of the newer ones are just for weather and chemical protection.
Tractor rollovers are the most common cause of fatal farm injuries, according to the National Safety Council. It estimates the annual death rate from rollovers in the United States is 5.4 per 100,000 tractors.
LSU AgCenter county agent Jimmy Flanagan, who tries to hold an annual farm safety educational meeting for agricultural producers in his area, says it's important for farmers to make farm safety information available to themselves, their families and their employees.
"We know farmers who provide access to these types of meetings have fewer on-farm accidents," Flanagan said. "Here in St. Mary Parish, we've had safety meetings since the mid-1980s and have had only four fatalities, while some of our neighboring parishes without meetings have had as many as 17 fatalities during the same period."
Gary Luke, owner of Baker Plantation in St. Mary Parish, said safety meetings on the farm are very worthwhile for his operation.
"I have safety meetings on my farm several times per year, especially when there is a change in weather," Luke said.
Luke, who farms 1,000 acres of cane and had a fatality the first year he farmed nearly 30 years ago, said he now sees that these meetings also help to lower his liability insurance and workers' compensation costs and helps to avoid lawsuits.
Louisiana Farm Bureau Safety Director Dick Beyer said that tractors are a big factor in farm injuries and death.
"Since 1974 there have been 203 farm fatalities in Louisiana involving tractors," Beyer said, stressing that while there are some farm safety meetings held around the state, he doesn't think there are nearly enough of them.
Beyer has been collecting clippings of farm fatalities for the past 30 years, and he brings his book of clippings to all of the safety meetings that he attends around the state to let the farmers and workers see the numbers. "I always tell the participants that this is one book that you don't want to be in," he said.
Louisiana Commissioner of Agriculture and Forestry Bob Odom said he applauds the LSU AgCenter's information and education effort to reach out to the farm community on the issue of farm safety.
"It is an issue that if we don't remind one another of occasionally, we tend to get lax," Odom said. "When we stop paying attention to the hazards farm equipment and farming situations can cause, we are asking for trouble for ourselves and our families."
For additional information on farm safety or information on how to set up a farm safety meeting in your parish, contact your local LSU AgCenter Extension office. Or for general information about the variety of programs offered by the LSU AgCenter, visit www.lsuagcenter.com.
David Bankston at (225) 578-2907 or firstname.lastname@example.com
Jimmy Flanagan at (337) 369-4441 or email@example.com
Johnny Morgan at (504) 838-1170 or firstname.lastname@example.com


text:
This web site is no longer available through this link. Please choose an alternative web site from the list shown below:
Alternative Web Sites
Now paying up to £45 for a dispatched order, and one the most established and recognised brands in the mobile phone industry, Mobile Phones Direct has over 20 years of experience and a large fan base of pay monthly customers. Dedicated to providing 'Smart deals on Smartphones', Mobile Phones Direct offer market leading pay monthly deals on the latest handsets on a clean and easy to use website. Combine this with high network accept and order dispatch rates, generous affiliate commissions that reward order volume, and no-nonsense daily order approvals, and you'll see your pay monthly conversion and profit rocket. All phones are stocked for next-day delivery, including Apple, Samsung, HTC, Blackberry, Nokia, Sony Ericsson, LG, Blackberry, Huawei, ZTE, plus Mobile Phones Direct runs frequent pre-order campaigns for new handsets up to 30 days prior to launch-date availability allowing it's affiliate partners to start earning early.
Click here to visit


text:
The original "Footloose" may have had an absurd premise and not even a tacit acknowledgement of the existence of people any color besides white, but it was an '80s movie, after all.
Its datedness — and director Herbert Ross's great, toe-tapping title sequence — is part of its kitschy charm. The cast, too, was exceptionally winning: Kevin Bacon as the upturned-collar out-of-towner, a radiant Lori Singer as the rebellious preacher's daughter, Chris Penn as the hayseed sidekick.
Why anyone should bother to remake it is an interesting question. It certainly could be substantially improved upon, but isn't that kind of like trying to build a better legwarmer?
From a monetary perspective (which is surely a dominant one here), this new "Footloose" situates the movie in the time of "Step Up" and the like. (The original followed the "Flashdance" craze.) From director Craig Brewer's point of view, the purpose is to add a little grit and a modicum of plausibility, while updating the teen rebellion of "Footloose" to a new generation who might not think playing chicken on tractors is high entertainment.
There's the ring of remix right from the get-go, with a DJ yelling "Check one, two" over Kenny Loggins' title track.
Kenny Wormald, a former back-up dancer for Justin Timberlake, slides into Bacon's dance shoes as Ren MacCormack. Wormald's MacCormack hails from Boston, not Chicago, and brings a Southie accent. Wormald is considerably better on his feet than Bacon, who needed dancing doubles.
Brewer, the talented Memphis director of "Hustle & Flow" and "Black Snake Moan," reprises much of the original "Footloose," scene for scene, sometimes shot for shot. But he also expands the film's world, fleshing out backstories and adding a little humor. He's shifted it to the South and made things sweatier.
Ren is shunned as an outsider in the small town of Bomont, Ga., where a recent tragedy has made the town clamp down on teenagers, even outlawing dancing. Ren quickly feels himself squeezed by small-mindedness, and he seeks release like any other teenager would: by furiously dancing in empty warehouses.
He soon sets his sights on Ariel (Julianne Hough), the daughter of the town preacher (Dennis Quaid, taking John Lithgow's place) and his wife (Andie MacDowell, in a step down from Dianne Wiest). Hough, also a dancing pro and multiple winner on "Dancing With the Stars," resembles the younger sister of Jennifer Aniston. Spending much of the film strutting in boots, she brings more sexiness to the movie.
The best casting decision is Miles Teller as Willard, the local who befriends Ren and gets the pleasure of the film's trademark dance-lesson montage. The gangly and excellent Ray McKinnon, as Ren's uncle, is also a considerable addition.
The two versions of "Footloose" are ultimately a tale of casting. In the original, a thoroughly likeable ensemble created a cheesy kind of movie magic out of paltry, laughable material. Brewer has made a better, more colorful film, but his cast isn't nearly as memorable.
The performances (excepting Teller's) are a paler shade of the original, and there's considerably less chemistry to go around. Wormald and Hough are both handsome and good on the dance floor, but they come across more like teen stars in training than representations of real youth angst.
Speaking of angst, one question: Line dancing? Brewer has added several updated dance sequences, including hip-hop and country line-dancing scenes. Yes, that wild, sinful expression of individuality known as country line dancing.
These kids may have better technique, but they don't have the moves.
"Footloose," a Paramount Pictures release, is rated PG-13 for some teen drug and alcohol use, sexual content, violence and language. Running time: 113 minutes. Two stars out of four.


text:
Knowing and the Known
Greenwood Press, 1960 - Philosophy - 334 pages
From inside the book
9 pages matching ostensive in this book
Where's the rest of this book?
Results 1-3 of 9
What people are saying - Write a review
We haven't found any reviews in the usual places.
Vagueness in Logic
The Terminological Problem
11 other sections not shown
Other editions - View all
Common terms and phrases
action activity application assertion behavior Bertrand Russell called Carnap Chapter characterization concept concern construction cosmos Designation designatum Dewey dictionary differentiation discussion disposition distinction employed entities environment epistemological Ernest Nagel event examination existence expression fact factual formulation G. E. Moore havior human indicate interactional interpretant involved John Dewey Journal of Philosophy knowings and knowns knowledge language linguistic locatum logical Logical Atomism logicians mathematical matter Max Wertheimer meaning ment Morris nature object observation ontological organism ostensive ostensive definition Peirce perhaps phase physical physiological postulations practical present problem procedure produced proposition psychology range respect Russell scientific self-actional semantics semiosis semiotic semiotician sentence separate sign-process signal significatum signify specification stage statement status stimulus stress subjectmatters symbol taken terminology Theory of Inquiry things tion transactional transactionally treatment Unified Science vague verbal warranted assertion


text:
A master of science in space systems from Florida Tech prepares students to perform in a wide variety of technical and managerial facets of private industry, government agencies or the military that are involved in the space program.
Accredited by the Southern Association of Colleges and Schools, the program trains graduates to plan, design, build, integrate, test launch, operate or manage all forms of space systems, subsystems, launch vehicles, spacecraft, payload or ground systems.
Space systems experts create enhanced cost efficiency and integration of new technologies. The master's in space systems competencies cover the critical systems that graduates find among their responsibilities in the workplace. This includes propulsion systems, power systems, spacecraft environment, astrodynamics, communications and data systems and spacecraft dynamics and control.
Students in this interdisciplinary degree program collaborate with colleagues in a variety of aerospace disciplines. Florida Tech professors are working professionals in the field, as are many of the students whose combined experience provides real-world insight about the industry. Students in the master's in space systems program complete a one-semester space mission team design project in lieu of a thesis.
Students come from diverse backgrounds and collaborate on research and project development, often published in noted industry magazines and journals. Assistantships at NASA, SpaceX and other commercial space companies offer a variety of hands-on space system design and operations experience for students earning a master's in space systems.
There are several career paths for individuals who earn a master's in space systems, including space systems engineer, space systems operations and space systems research. Graduates from Florida Tech are hired by private and government organizations, including Harris Corporation, Boeing, the U.S military, the European Space Agency, Federal Aviation Agency and NASA, among others. Two graduates of the program became NASA astronauts.


text:
P.M. Three Strikes: Daughter of burglar awarded $300,000 in make-my-day robbery turned ambush
Saturday afternoon's new round-up delayed by a reporter's morning search for a 40 pound fish.
LEADING OFF: After a two-week-long civil trial, an El Paso County jury awarded almost $300,000 to the daughter of a burglar who was fatally shot in 2009, after the owners of a Colorado Springs auto lot ambushed the man instead of waiting for police.
STRIKE 1: Carlos Illescas reports about the Aurora City Council's tentative agreement with the police union to lower a requirement that the city must hire two police officers for every 1,000 residents. The Denver Post's Kieran Nicholson reveals details around the arrest of Arvada High School's assistant principal, accused of sexually assaulting a female student. Sara Burnett and I detail the plea agreement extended to the 12-year-old Burlington boy accused of killing his parents and attacking his younger siblings.


text:
Organizers of a toy drive for families in need are inviting the public to chip in at a gift-wrapping party.
Organizers of a toy drive for families in need are inviting the public to chip in at a gift-wrapping party.
The drive, called Everlasting Smiles, gives wrapped toys during the holidays through the local nonprofit Charterhouse Center for Families. The event is from 5:30 to 9 p.m. Dec. 10 at the Brookside Country Club, 3603 St. Andrews Drive, Stockton.
Those coming should bring their family and a gift, so they can pick the name of a child in need to give it to, according to organizers. Food and drinks will be provided.
Information: Brookside General Insurance Services, Inc., (209) 476-8022.
Meet at the Glory Hole Entrance Station at 10 a.m. Dec. 8 for a moderate three-mile hike along the Angels Creek trail to find evidence of people of the past. Parking pass provided.
Information: (209) 536-9543.
A Mature Driver Safety class for people 55 and older will be Dec. 13 and Jan. 19. Training provides a DMV certificate valid for three years, eligibility for a discount on auto insurance, and information helpful for passing license renewal exams. Call for prices and times.
Information: (209) 472-7233 or californiasafety.org.
Maps for the Holiday House Tour and Concert will be available from noon to 1 p.m. Dec. 15 at 7869 Whiskey Slide Road, Mountain House.
A concert by Mountain Melody will be held at the final house. Refreshments will be provided. The suggested donation is $20.
Information: (209) 754-4073.
Application deadline for the Soroptimist International of Calaveras County Women's Opportunity Awards is Dec. 15. The program assists women with primary financial responsibility for their families to obtain skills training and education needed to improve employment status. Award money may be used for any educational cost. Application requests emailed to firstname.lastname@example.com.
Information: soroptimist.org.
Meet at the intersection of Shell and Rawhide Roads for an easy two-mile winter landscape photography hike 10 a.m. Dec. 16. Cameras, owner manuals and tripods needed.
Information: (209) 536-9543.


text:
Hello guys,
Just wanted to keep you posted on the demos we have been having here on the Outer Banks, North Carolina (USA). It has been incredible. The only problem is that I need to put more demo kites into the demo fleet because of the demand.
These demos started March 27th and will keep going until July 25 "2012".
Any one interested in demoing any (2011, 3G, and 3GII) product such as:
-RENEGADES kites model (5/7/9/11/13, Infinity v2)
-SCREAMER kites model (7/9/12/14) & SCREAMER 10 LTD plus the new (4G) S10 ltd prototype.
-JUDGE kites model (6/8/11)
-TUTOR trainer kite
-JUNIOR PRO 4 kite for kids
-REEF SURF BOARDS (5'7" & 5'11" or the new V2 5'7" & 6'0")
-TWIN TIPS BOARDS (Spartan,Droid, Oxygen, Junior Pro)
and so on can reach us via email at: firstname.lastname@example.com or through this post.
Once again, I hope to see you in the water no matter what brand you ride. Let's have an epic time.
P.S. Will be posting more EPIC demo pictures very soon.


text: Totally stoked to get on the road around the end of June. I will be leaving from Ottawa to Inuvik and then hopefully to Tierra Del Fuego via the Amazon, I guess time will tell if this is a good idea or not. Have been preparing for the last 7 months to go on this ride that will take equally as long to do, luckily I don't have any must ride road or time constraints, its going to be more like lets see if I can make it. I did read many ride reports from inmates here on ADVrider, and I can only hope to bring some of there words of wisdom into practice and follow some of the roads they drove to discover on my own. One particular RR I read from Debbie aka Hewby says it so well Motorcycle riding adds an extra dimension of adventure and freedom. Winding roads through valleys and over mountains, the bike seems to dance beneath me. Passing along the country side or through the forest, the smells become intoxicating. And the Vrrmmm of the engine gives me a sense of power, freedom, excitement and connectedness this struck a cord in me and I thought this is how I feel too. Thank you Debbie for saying it so well I hope I did get it right and you don't mind me steeling that one from you. This RR will be to document my trip, let my friends and family know where I am and how I'm doing, and then of course let you join in on the fun. During the trip I will also give border crossing updates, budget info, and try to make this as entertaining as I possibly can, I am by no means a writing star and my sense of language is screwed up. I hope to make use of the ADVriders free camping page mainly because riding and spending a big budget on this trip was not an option. I could have waited a couple more years, but at an age of 62 I feel it's now or maybe never. Its funny how things sometimes come up in life and you wonder why, or have some weird deja vu moment or so, because I do believe in karma and destiny, more on this later. This trip has been on my mind for a long time, and newly inspired by a video that I had accidentally seen from Globebusters, after that video I could not shake the idea of not doing it, it kind of said it all to me, after seeing there smiling faces on that trip, and of course there stories just topped it off, I need to do this. A little bit about myself, born in the Netherlands and moved to the USA when I was 1 year old, lived in Salt Lake City, for 16 years and then moved back to the Netherlands, got married, had two kids and moved to Canada, did tons of motorcycle riding throughout most of Europe, and now the same in Canada and the USA. Im very lucky that my lovely wife (Annie) and my two sons (Ray and Bob) support me in going, although this was not so much in the beginning when I told them, but they have warmed up to it, Annie would have loved to have come along as we did throughout most of our travels in Europe, but this is physically not possible for her anymore. I also have a great group of supporters from the Ottawa Canadian Motorcycle Cruisers (CMC), which I like to think of as my extended family, through the years we have done many great rides together with tons of laughs along the way. During this trip I will try to hook-up with other ADVriders and also visit some of the other CMC chapters throughout Canada and extend a welcoming hand to all for a visit to Ottawa someday, Next post will be more about my bike and gear, so stay tuned. Jeff Luttmer


text:
As mentioned on Blogoscoped.com, I did a radio interview this week with Jeff Horwich about Google. It was a lot of fun and thanks again to Georgia Public Broadcasting as well as Minnesota Public Radio for making me sound so good!
"The Week" September 12, 2008 from In The Loop. (My interview starts about 14 minutes into the show and is available at npr.org/...)
"* Congress back in session: Will they actually get anything done? We talk with Kathryn Pearson of the University of Minnesota.
* Trouble naming your baby? Sarah Palin's here to help.
* Brian Ussery of Blogoscoped.com joins us for The Week in Google (it was a big week)
* The Wall Street Journal's Vanessa O'Connell on new employee management software
* "Too Big to Fail"...sounds like a John Prine song to me"