
scales.utils.resources.Resources.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scales-xml_2.11 Show documentation
Show all versions of scales-xml_2.11 Show documentation
An alternate Scala Xml processing library
The newest version!
package scales.utils.resources
trait IsClosed {
def isClosed : Boolean
}
/**
* Mostly exists for pulling but it is general
*
* We want to enable bracketing and a more orderly shutdown of resources from the input streams.
* Whilst the resource is closed automatically its not very helpful if you don't want to close it.
* Due to Sun bug: 6539065 we have to wrap the actual close. This allows us to decide IF we want to close.
*
* So we cover three use cases here:
* * Enumeratees can bracket, if so desired
* * Streams of xml can be continuously plied for more xml messages
* * Users who want to manually close early can do so too.
*
* As a note this fits very closely to the scala-arm stuff, which I happily use in another project. But it has
* two specific seperate use cases:
* * XmlPulls should be joinable as iterators ++ should ensure that the resources are closed
* * Additionally, however, closing on the resulting XmlPull should close the lot.
*
* So we either override the ++ to behave differently or we abstract away using of the stream from closing it.
*
*/
trait CloseOnNeed extends IsClosed {
parent =>
protected def doClose : Unit
private[utils] var closed = false
def isClosed = closed
/**
* Close the underlying something, but only do it once.
*
* This allows closing of an xml input stream directly after the end doc, but without disturbing
* the normal model.
*/
def closeResource =
if (!closed) {
closed = true;
doClose
} else ()
def ++( close2 : CloseOnNeed ) : CloseOnNeed = new CloseOnNeed {
added =>
def doClose = ()
override def closeResource =
if (!closed) {
closed = true;
parent.closeResource
close2.closeResource
} else ()
// flip it back to stop from endlessly repeating ourselves
override def ++(close3 : CloseOnNeed) = {
close3 ++ this
}
}
}
/**
* Simple pool interface
*/
trait Pool[T] {
def grab : T
def giveBack( t : T ) : Unit
}
/**
* Thread safe unbounded pool, if more objects are required it will simple create them. The optional parameter reduceSize tries to help clean up a bit when an excessive amount is created but does not act as a semaphore
*/
trait SimpleUnboundedPool[T] extends Pool[T] with Loaner[T] with Creator[T] {
val reduceSize : Int = 30
val size = new java.util.concurrent.atomic.AtomicInteger(0)
private[this] val cache = new java.util.concurrent.ConcurrentLinkedQueue[T]();
def grab = {
val res = cache.poll
if (res != null) res
else doCreate
}
def giveBack( t : T ) {
if (size.get > reduceSize) size.decrementAndGet
else cache.add(t)
}
final def doCreate = {
size.getAndIncrement()
create
}
/**
* Performs a loan for you
*/
def loan[X]( tThunk : T => X ) : X = {
var t = null.asInstanceOf[T]
try {
t = grab // can throw
tThunk(t)
} finally {
if (t != null) giveBack(t)
}
}
}
trait Loaner[T] {
/**
* Performs a loan for you
*/
def loan[X]( tThunk : T => X ) : X
}
/**
* Simple factory interface
*/
trait Creator[T] {
def create : T
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy