Files
swift-mirror/validation-test/stdlib/StringSlicesConcurrentAppend.swift
Dmitri Hrybenko 581dc3c35d stdlib: split topic-focused modules out of StdlibUnittest
The new modules are:

* SwiftUnstable -- assorted additions to the core standard library
  (more algorithms etc.)

* SwiftUnstableDarwinExtras -- proposed additions to the Darwin overlay,
  not yet reviewed by the Darwin team.

* SwiftUnstablePthreadExtras -- wrappers that make it possible to
  use pthread in Swift (they work around the lack of block-based API in
  pthread).  In future these could be possibly folded into the Darwin
  overlay as well.

These APIs are useful without StdlibUnittest for writing automation
tools in Swift.  Just like SwiftExperimental, none of these modules are
exposed to extrenal users.

Also, since these new modules can be compiled with -sil-serialize-all
(unlike StdlibUnittest, where we can't apply the flag because of
compiler bugs), standard library tests that need to run optimized code
(like AtomicInt.swift) are *much* faster now.

Swift SVN r25679
2015-03-02 10:38:42 +00:00

116 lines
2.7 KiB
Swift

// RUN: %target-run-stdlib-swift
// XFAIL: linux
import Swift
import StdlibUnittest
import SwiftUnstablePthreadExtras
import Dispatch
var StringTestSuite = TestSuite("String")
extension String {
var bufferID: UWord {
return unsafeBitCast(_core._owner, UWord.self)
}
var capacityInBytes: Int {
return _core.nativeBuffer!.capacity
}
}
// Swift.String has an optimization that allows us to append to a shared string
// buffer. Make sure that it works correctly when two threads try to append to
// different non-shared strings that point to the same shared buffer.
enum ThreadID {
case Master
case Slave
}
var barrierVar: UnsafeMutablePointer<_stdlib_pthread_barrier_t> = nil
var sharedString: String = ""
var slaveString: String = ""
func barrier() {
var ret = _stdlib_pthread_barrier_wait(barrierVar)
expectTrue(ret == 0 || ret == _stdlib_PTHREAD_BARRIER_SERIAL_THREAD)
}
func sliceConcurrentAppendThread(tid: ThreadID) {
for i in 0..<100 {
barrier()
if tid == .Master {
// Get a fresh buffer.
sharedString = ""
sharedString.extend("abc")
sharedString.reserveCapacity(16)
expectLE(16, sharedString.capacityInBytes)
}
barrier()
// Get a private string.
var privateString = sharedString
barrier()
// Append to the private string.
if tid == .Master {
privateString.extend("def")
} else {
privateString.extend("ghi")
}
barrier()
// Verify that contents look good.
if tid == .Master {
expectEqual("abcdef", privateString)
} else {
expectEqual("abcghi", privateString)
}
expectEqual("abc", sharedString)
// Verify that only one thread took ownership of the buffer.
if tid == .Slave {
slaveString = privateString
}
barrier()
if tid == .Master {
expectTrue(
(privateString.bufferID == sharedString.bufferID) !=
(slaveString.bufferID == sharedString.bufferID))
}
}
}
StringTestSuite.test("SliceConcurrentAppend") {
barrierVar = UnsafeMutablePointer.alloc(1)
barrierVar.initialize(_stdlib_pthread_barrier_t())
var ret = _stdlib_pthread_barrier_init(barrierVar, nil, 2)
expectEqual(0, ret)
let (createRet1, tid1) = _stdlib_pthread_create_block(
nil, sliceConcurrentAppendThread, .Master)
let (createRet2, tid2) = _stdlib_pthread_create_block(
nil, sliceConcurrentAppendThread, .Slave)
expectEqual(0, createRet1)
expectEqual(0, createRet2)
let (joinRet1, _) = _stdlib_pthread_join(tid1!, Void.self)
let (joinRet2, _) = _stdlib_pthread_join(tid2!, Void.self)
expectEqual(0, joinRet1)
expectEqual(0, joinRet2)
ret = _stdlib_pthread_barrier_destroy(barrierVar)
expectEqual(0, ret)
barrierVar.destroy()
barrierVar.dealloc(1)
}
runAllTests()