Skip to content

Initial Swift3 wrapping overlay for libdispatch #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ AS_IF([test "x$enable_apple_tsd_optimizations" = "xyes"],
[Define to use non-portable pthread TSD optimizations for Mac OS X)])]
)

AC_CANONICAL_TARGET

#
# Enable building Swift overlay support into libdispatch
#
Expand All @@ -102,17 +104,34 @@ AC_ARG_WITH([swift-toolchain],
[swift_toolchain_path=${withval}
AC_DEFINE(HAVE_SWIFT, 1, [Define if building for Swift])
SWIFTC="$swift_toolchain_path/bin/swiftc"
case $target_os in
linux*)
os_string="linux"
;;
*)
os_string=$target_os
;;
esac
SWIFT_LIBDIR="$swift_toolchain_path/lib/swift/$os_string/$target_cpu"
have_swift=true],
[have_swift=false]
)
AM_CONDITIONAL(HAVE_SWIFT, $have_swift)
AC_SUBST([SWIFTC])
AC_SUBST([SWIFT_LIBDIR])

#
# Enable use of gold linker when building the Swift overlay
# to avoid a symbol relocation issue.
# Ultimately the request to use gold should be passed in as an arg
#
AC_CHECK_PROG(use_gold_linker, ld.gold, true, false)
AM_CONDITIONAL(USE_GOLD_LINKER, $use_gold_linker)

#
# Enable __thread based TSD on platforms where it is efficient
# Allow override based on command line argument to configure
#
AC_CANONICAL_TARGET
AC_ARG_ENABLE([thread-local-storage],
[AS_HELP_STRING([--enable-thread-local-storage],
[Enable usage of thread local storage via __thread])],,
Expand Down
2 changes: 1 addition & 1 deletion dispatch/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ dispatch_HEADERS= \
time.h

if HAVE_SWIFT
dispatch_HEADERS+=module.map
dispatch_HEADERS+=module.modulemap
endif
7 changes: 0 additions & 7 deletions dispatch/module.map

This file was deleted.

16 changes: 13 additions & 3 deletions dispatch/module.modulemap
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
module Dispatch [system] [extern_c] {
umbrella header "dispatch.h"
module * { export * }
module Dispatch {
requires blocks
export *
link "dispatch"
link "BlocksRuntime"
}

module DispatchIntrospection [system] [extern_c] {
header "introspection.h"
export *
}

module CDispatch [system] [extern_c] {
umbrella header "dispatch.h"
module * { export * }
export *
requires blocks
link "dispatch"
link "BlocksRuntime"
}
70 changes: 46 additions & 24 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ libdispatch_la_SOURCES= \
source_internal.h \
trace.h \
voucher_internal.h \
firehose/firehose_internal.h \
shims/atomic.h \
shims/atomic_sfb.h \
shims/getprogname.h \
Expand Down Expand Up @@ -83,6 +84,10 @@ libdispatch_la_LDFLAGS+=-Wl,-compatibility_version,1 \
-Wl,-alias_list,$(top_srcdir)/xcodeconfig/libdispatch.aliases
endif

if USE_GOLD_LINKER
libdispatch_la_LDFLAGS+=-Xcompiler -fuse-ld=gold
endif

if USE_OBJC
libdispatch_la_SOURCES+=block.cpp data.m object.m
libdispatch_la_OBJCFLAGS=$(AM_OBJCFLAGS) -Wno-switch -fobjc-gc
Expand Down Expand Up @@ -114,43 +119,60 @@ DTRACE_SOURCES=provider.h
endif

if HAVE_SWIFT
libdispatch_la_SOURCES+=swift/Dispatch.mm
EXTRA_libdispatch_la_SOURCES+= \
swift/Dispatch.swift \
SWIFT_SRC_FILES=\
swift/Block.swift \
swift/Data.swift \
swift/Dispatch.swift \
swift/IO.swift \
swift/Private.swift \
swift/Queue.swift \
swift/Source.swift \
swift/Time.swift

EXTRA_libdispatch_la_DEPENDENCIES+=$(abs_builddir)/Dispatch.o $(abs_builddir)/Dispatch.swiftmodule
libdispatch_la_LIBADD+=$(abs_builddir)/Dispatch.o

SWIFT_OBJECTS= \
$(abs_builddir)/Dispatch.swiftmodule \
$(abs_builddir)/Dispatch.swiftdoc \
$(abs_builddir)/Dispatch.o
swift/Time.swift \
swift/Wrapper.swift

SWIFT_ABS_SRC_FILES = $(SWIFT_SRC_FILES:%=$(abs_srcdir)/%)
SWIFT_OBJ_FILES = $(SWIFT_SRC_FILES:%.swift=$(abs_builddir)/%.o)

libdispatch_la_SOURCES+=swift/DispatchStubs.cc
EXTRA_libdispatch_la_SOURCES+=$(SWIFT_SRC_FILES)

EXTRA_libdispatch_la_DEPENDENCIES+=$(SWIFT_OBJ_FILES) $(abs_builddir)/swift/Dispatch.swiftmodule
libdispatch_la_LIBADD+=$(SWIFT_OBJ_FILES)

SWIFT_GEN_FILES= \
$(abs_builddir)/swift/Dispatch.swiftmodule \
$(abs_builddir)/swift/Dispatch.swiftdoc \
$(SWIFT_OBJ_FILES) \
$(SWIFT_OBJ_FILES:%=%.d) \
$(SWIFT_OBJ_FILES:%=%.swiftdeps) \
$(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \
$(SWIFT_OBJ_FILES:%=%.~partial.swiftdoc) \
$(SWIFT_OBJ_FILES:%=%.~partial.swiftdeps)

SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.modulemap -I$(abs_top_srcdir) -Xcc -fblocks

$(abs_builddir)/swift/%.o: $(abs_srcdir)/swift/%.swift
$(SWIFTC) -frontend -c $(SWIFT_ABS_SRC_FILES) -primary-file $< \
$(SWIFTC_FLAGS) -module-name Dispatch -module-link-name dispatch \
-o $@ -emit-module-path $@.~partial.swiftmodule \
-emit-module-doc-path $@.~partial.swiftdoc -emit-dependencies-path $@.d \
-emit-reference-dependencies-path $@.swiftdeps \
-module-cache-path $(top_builddir)

$(abs_builddir)/swift/Dispatch.swiftmodule: $(SWIFT_ABS_SRC_FILES)
$(SWIFTC) -frontend -emit-module $(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \
$(SWIFTC_FLAGS) -module-cache-path $(top_builddir) -module-link-name dispatch \
-o $@ -emit-module-doc-path $(@:%.swiftmodule=%.swiftdoc)

SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.map -I$(abs_top_srcdir) -parse-as-library -Xcc -fblocks

$(abs_builddir)/Dispatch.o: $(abs_srcdir)/swift/Dispatch.swift
$(SWIFTC) $(SWIFTC_FLAGS) -c -o $@ $<

$(abs_builddir)/Dispatch.swiftmodule: $(abs_srcdir)/swift/Dispatch.swift
$(SWIFTC) $(SWIFTC_FLAGS) -emit-module -emit-module-path $@ $<

if HAVE_SWIFT
swiftmoddir=${prefix}/lib/swift/linux/${build_cpu}
swiftmod_HEADERS=$(abs_builddir)/Dispatch.swiftmodule $(abs_builddir)/Dispatch.swiftdoc
endif
swiftmod_HEADERS=\
$(abs_builddir)/swift/Dispatch.swiftmodule \
$(abs_builddir)/swift/Dispatch.swiftdoc

endif

BUILT_SOURCES=$(MIG_SOURCES) $(DTRACE_SOURCES)
nodist_libdispatch_la_SOURCES=$(BUILT_SOURCES)
CLEANFILES=$(BUILT_SOURCES) $(SWIFT_OBJECTS)
CLEANFILES=$(BUILT_SOURCES) $(SWIFT_GEN_FILES)
DISTCLEANFILES=pthread_machdep.h pthread System mach objc

4 changes: 4 additions & 0 deletions src/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ const dispatch_block_t _dispatch_data_destructor_none = ^{
DISPATCH_INTERNAL_CRASH(0, "none destructor called");
};

const dispatch_block_t _dispatch_data_destructor_munmap = ^{
DISPATCH_INTERNAL_CRASH(0, "munmap destructor called");
};

#ifndef __linux__
const dispatch_block_t _dispatch_data_destructor_vm_deallocate = ^{
DISPATCH_INTERNAL_CRASH(0, "vmdeallocate destructor called");
Expand Down
49 changes: 16 additions & 33 deletions src/swift/Block.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
//
//===----------------------------------------------------------------------===//

import CDispatch

public struct DispatchWorkItemFlags : OptionSet, RawRepresentable {
public let rawValue: UInt
public init(rawValue: UInt) { self.rawValue = rawValue }
Expand Down Expand Up @@ -38,14 +40,14 @@ public class DispatchWorkItem {
internal var _group: DispatchGroup?

public init(group: DispatchGroup? = nil, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], block: @convention(block) () -> ()) {
_block = _swift_dispatch_block_create_with_qos_class(__dispatch_block_flags_t(flags.rawValue),
qos.qosClass.rawValue, Int32(qos.relativePriority), block)
_block = dispatch_block_create_with_qos_class(dispatch_block_flags_t(flags.rawValue),
qos.qosClass.rawValue.rawValue, Int32(qos.relativePriority), block)
}

// Used by DispatchQueue.synchronously<T> to provide a @noescape path through
// dispatch_block_t, as we know the lifetime of the block in question.
internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: @noescape () -> ()) {
_block = _swift_dispatch_block_create_noescape(__dispatch_block_flags_t(flags.rawValue), noescapeBlock)
_block = _swift_dispatch_block_create_noescape(dispatch_block_flags_t(flags.rawValue), noescapeBlock)
}

public func perform() {
Expand All @@ -57,36 +59,36 @@ public class DispatchWorkItem {
}

public func wait() {
_ = _swift_dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue)
_ = dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue)
}

public func wait(timeout: DispatchTime) -> DispatchTimeoutResult {
return _swift_dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut
return dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut
}

public func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult {
return _swift_dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .Success : .TimedOut
return dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .Success : .TimedOut
}

public func notify(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute: @convention(block) () -> Void) {
if qos != .unspecified || !flags.isEmpty {
let item = DispatchWorkItem(qos: qos, flags: flags, block: execute)
_swift_dispatch_block_notify(_block, queue, item._block)
dispatch_block_notify(_block, queue.__wrapped, item._block)
} else {
_swift_dispatch_block_notify(_block, queue, execute)
dispatch_block_notify(_block, queue.__wrapped, execute)
}
}

public func notify(queue: DispatchQueue, execute: DispatchWorkItem) {
_swift_dispatch_block_notify(_block, queue, execute._block)
dispatch_block_notify(_block, queue.__wrapped, execute._block)
}

public func cancel() {
_swift_dispatch_block_cancel(_block)
dispatch_block_cancel(_block)
}

public var isCancelled: Bool {
return _swift_dispatch_block_testcancel(_block) != 0
return dispatch_block_testcancel(_block) != 0
}
}

Expand All @@ -96,7 +98,7 @@ public extension DispatchWorkItem {
public func wait(timeout: DispatchWallTime) -> Int {
switch wait(wallTimeout: timeout) {
case .Success: return 0
case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT)
case .TimedOut: return DispatchTimeoutResult.KERN_OPERATION_TIMED_OUT
}
}
}
Expand All @@ -106,26 +108,7 @@ public extension DispatchWorkItem {
/// C blocks and Swift closures, which interferes with dispatch APIs that depend
/// on the referential identity of a block. Particularly, dispatch_block_create.
internal typealias _DispatchBlock = @convention(block) () -> Void

/// APINotes also removes the old dispatch_block_t typedef from the Dispatch module
/// completely. In doing so it causes the dispatch_block_* API to lose their
/// @convention(block) attributes. As such, all of the entry points are shimmed
//// through Dispatch.mm with _DispatchBlock types.
@_silgen_name("_swift_dispatch_block_create_with_qos_class")
internal func _swift_dispatch_block_create_with_qos_class(_ flags: __dispatch_block_flags_t, _ qos: qos_class_t, _ relativePriority: Int32, _ block: _DispatchBlock) -> _DispatchBlock
internal typealias dispatch_block_t = @convention(block) () -> Void

@_silgen_name("_swift_dispatch_block_create_noescape")
internal func _swift_dispatch_block_create_noescape(_ flags: __dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock

@_silgen_name("_swift_dispatch_block_wait")
internal func _swift_dispatch_block_wait(_ block: _DispatchBlock, _ timeout: UInt64) -> Int

@_silgen_name("_swift_dispatch_block_notify")
internal func _swift_dispatch_block_notify(_ block: _DispatchBlock, _ queue: DispatchQueue, _ notifier: _DispatchBlock)

@_silgen_name("_swift_dispatch_block_cancel")
internal func _swift_dispatch_block_cancel(_ block: _DispatchBlock)

@_silgen_name("_swift_dispatch_block_testcancel")
internal func _swift_dispatch_block_testcancel(_ block: _DispatchBlock) -> Int

internal func _swift_dispatch_block_create_noescape(_ flags: dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock
Loading