Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
djinni
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
djinni
Commits
3a1c6421
Commit
3a1c6421
authored
Sep 22, 2015
by
Jacob Potter
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extension libraries for platform threading and custom exception translation.
parent
b0e39230
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
549 additions
and
0 deletions
+549
-0
extension-libs/extension-libs.iml
extension-libs/extension-libs.iml
+9
-0
extension-libs/jni-exceptions/custom_exception_type.cpp
extension-libs/jni-exceptions/custom_exception_type.cpp
+92
-0
extension-libs/platform-threads/android/com/dropbox/djinni/extension_libs/platform_threads/AndroidPlatformThreads.java
...tension_libs/platform_threads/AndroidPlatformThreads.java
+55
-0
extension-libs/platform-threads/cpp/platform_threads_impl.hpp
...nsion-libs/platform-threads/cpp/platform_threads_impl.hpp
+102
-0
extension-libs/platform-threads/djinni/platform-threads.djinni
...sion-libs/platform-threads/djinni/platform-threads.djinni
+20
-0
extension-libs/platform-threads/java/com/dropbox/djinni/extension_libs/platform_threads/JavaPlatformThreads.java
.../extension_libs/platform_threads/JavaPlatformThreads.java
+76
-0
extension-libs/platform-threads/objc/DJIObjCPlatformThreads.h
...nsion-libs/platform-threads/objc/DJIObjCPlatformThreads.h
+65
-0
extension-libs/platform-threads/objc/DJIObjCPlatformThreads.m
...nsion-libs/platform-threads/objc/DJIObjCPlatformThreads.m
+88
-0
extension-libs/platform-threads/platform-threads.gyp
extension-libs/platform-threads/platform-threads.gyp
+41
-0
src/.idea/modules.xml
src/.idea/modules.xml
+1
-0
No files found.
extension-libs/extension-libs.iml
0 → 100644
View file @
3a1c6421
<?xml version="1.0" encoding="UTF-8"?>
<module
type=
"WEB_MODULE"
version=
"4"
>
<component
name=
"NewModuleRootManager"
inherit-compiler-output=
"true"
>
<exclude-output
/>
<content
url=
"file://$MODULE_DIR$"
/>
<orderEntry
type=
"inheritedJdk"
/>
<orderEntry
type=
"sourceFolder"
forTests=
"false"
/>
</component>
</module>
\ No newline at end of file
extension-libs/jni-exceptions/custom_exception_type.cpp
0 → 100644
View file @
3a1c6421
/**
* Copyright 2015 Dropbox, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This is an example of how to replace Djinni's default JNI exception translation functions
* to provide custom behavior. For this example, we show how to convert specific Java exception
* types to custom C++ exception types.
*/
#include <exception>
#include "../../../support-lib/jni/djinni_support.hpp"
using
namespace
djinni
;
/*
* Custom C++ exception I want to throw in response to a Java security exception.
* In production code, you'd want to put this in a header, so other C++ code can throw and
* catch it.
*/
class
my_security_exception
:
public
std
::
runtime_error
{
public:
my_security_exception
(
const
std
::
string
&
what_arg
)
:
runtime_error
(
what_arg
)
{};
};
/*
* Helper type to prepare and cache all the Java type and method lookups we need.
*/
struct
SecurityExceptionClassInfo
{
const
GlobalRef
<
jclass
>
clazz
=
djinni
::
jniFindClass
(
"java/lang/SecurityException"
);
const
jmethodID
ctor
=
djinni
::
jniGetMethodID
(
clazz
.
get
(),
"<init>"
,
"(Ljava/lang/String;)V"
);
const
jmethodID
getMessage
=
djinni
::
jniGetMethodID
(
clazz
.
get
(),
"getMessage"
,
"()Ljava/lang/String;"
);
};
/*
* We're replacing pluggable functions inside the djinni namespace.
*/
namespace
djinni
{
/*
* Pluggable Djinni translation function for C++ -> Java. Called when a call
* from Java to C++ throws an exception. Called inside a catch block.
*
* The default implementation is defined with __attribute__((weak)) so this
* definition can replace it.
*/
void
jniSetPendingFromCurrent
(
JNIEnv
*
env
,
const
char
*
ctx
)
noexcept
{
try
{
throw
;
}
catch
(
const
my_security_exception
&
e
)
{
const
SecurityExceptionClassInfo
&
ci
=
djinni
::
JniClass
<
SecurityExceptionClassInfo
>::
get
();
LocalRef
<
jstring
>
jmessage
{
env
,
jniStringFromUTF8
(
env
,
e
.
what
())
};
LocalRef
<
jthrowable
>
jex
{
env
,
(
jthrowable
)
env
->
NewObject
(
ci
.
clazz
.
get
(),
ci
.
ctor
,
jmessage
.
get
())
};
env
->
Throw
(
jex
);
return
;
}
catch
(
const
std
::
exception
&
e
)
{
jniDefaultSetPendingFromCurrent
(
env
,
ctx
);
}
}
/*
* Pluggable Djinni translation function for Java -> C++. Called when a call
* from C++ to Java throws an exception.
*
* The default implementation is defined with __attribute__((weak)) so this
* definition can replace it.
*/
void
jniThrowCppFromJavaException
(
JNIEnv
*
env
,
jthrowable
java_exception
)
{
const
SecurityExceptionClassInfo
&
ci
=
djinni
::
JniClass
<
SecurityExceptionClassInfo
>::
get
();
if
(
env
->
IsInstanceOf
(
java_exception
,
ci
.
clazz
.
get
()))
{
LocalRef
<
jstring
>
jmessage
{
env
,
(
jstring
)
env
->
CallObjectMethod
(
java_exception
,
ci
.
getMessage
)
};
throw
my_security_exception
(
jniUTF8FromString
(
env
,
jmessage
.
get
()));
}
throw
jni_exception
{
env
,
java_exception
};
}
}
// namespace djinni
extension-libs/platform-threads/android/com/dropbox/djinni/extension_libs/platform_threads/AndroidPlatformThreads.java
0 → 100644
View file @
3a1c6421
//
// Copyright 2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
// Note: This is a sample implementation which interacts with Djinni-generated code.
// You may need to adjust names and packages to match the settings of code
// generation in your project.
//
package
com.dropbox.djinni.extension_libs.platform_threads
;
import
javax.annotation.CheckForNull
;
import
javax.annotation.Nonnull
;
import
android.os.Looper
;
/**
* Cross-language platform thread implementation for Android Java.
* Create a subclass and override configureThread() to customize the created threads.
*/
public
class
AndroidPlatformThreads
extends
JavaPlatformThreads
{
private
static
Looper
sMainLooper
=
Looper
.
getMainLooper
();
/**
* Creates an instance.
*/
public
AndroidPlatformThreads
()
{}
/**
* Determines whether the calling thread is the main UI thread of the
* app. Some platforms do not have a notion of a main thread, in which
* case this method returns null.
*
* This implementation returns true or false based on the Android UI's
* notion of a main thread.
*/
@Override
@Nonnull
public
Boolean
isMainThread
()
{
return
Looper
.
myLooper
()
==
sMainLooper
;
}
}
extension-libs/platform-threads/cpp/platform_threads_impl.hpp
0 → 100644
View file @
3a1c6421
//
// Copyright 2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
// Note: This is a sample implementation which interacts with Djinni-generated code.
// You may need to adjust names or include paths to match the settings of code
// generation in your project.
//
#include "platform_threads.hpp"
#include "thread_func.hpp"
#include <functional>
namespace
djinni
{
namespace
extension_libs
{
namespace
platform_threads
{
/**
* Pure C++ implementation of PlatformThreads, using std::thread.
* Note that thread names are ignored by this class.
*
* This implementation abstracts away the type of pointers to thread objects.
* By default, use CppPlatformThreads defined below. If you use non-nullable pointers,
* you may want to instantiate CppPlatformThreadsGeneric with a different type.
*/
template
<
typename
ThreadFuncPtr
>
class
CppPlatformThreadsGeneric
:
public
PlatformThreads
{
public:
/** Implementation with default thread configuration. */
CppPlatformThreadsGeneric
()
:
m_func_on_thread_start
(
nullptr
)
{};
/**
* Implementation which will call the given function on each new thread after
* it starts, before calling the normal ThreadFunc.
*/
CppPlatformThreadsGeneric
(
std
::
function
<
void
()
>
func_on_thread_start
)
:
m_func_on_thread_start
(
make_shared
<
std
::
function
<
void
()
>>
(
std
::
move
(
func_on_thread_start
)))
{}
/** Creates and starts a new thread which will call the given function. */
virtual
void
create_thread
(
const
std
::
string
&
/*name*/
,
const
ThreadFuncPtr
&
func
)
override
final
{
std
::
thread
([
run_func
=
std
::
move
(
func
),
start_func
=
m_func_on_thread_start
]()
{
if
(
start_func
&&
*
start_func
)
{
(
*
start_func
)();
}
run_func
->
run
();
}).
detach
();
}
/**
* Determines whether the calling thread is the main UI thread of the
* app. Some platforms do not have a notion of a main thread, in which
* case this method returns null.
*
* This implementation returns null since C++ doesn't have any default
* notion of a main/UI thread. Platform-specific subclasses may override.
*/
virtual
std
::
experimental
::
optional
<
bool
>
is_main_thread
()
override
final
{
return
nullopt
;
}
private:
const
shared_ptr
<
std
::
function
<
void
()
>>
m_func_on_thread_start
;
};
/**
* Instantiation of CppPlatformThreadsGeneric with standard pointers.
*/
using
CppPlatformThreads
=
CppPlatformThreadsGeneric
<
std
::
shared_ptr
<
ThreadFunc
>>
;
/** Standard implementation of Djinni thread_func using std::function. */
class
ThreadFuncImpl
final
:
public
ThreadFunc
{
public:
/**
* Implicit constructor allowing std::function<void()> to be passed
* where ThreadFunc is expected.
*/
ThreadFuncImpl
(
std
::
function
<
void
()
>
func
)
:
m_func
(
std
::
move
(
func
))
{}
/** Will be run on thread start. The thread will exit when this returns. */
virtual
void
run
()
override
final
{
m_func
();
}
private:
const
std
::
function
<
void
()
>
m_func
;
};
}
}
}
// namespace djinni::extension_libs::platform_threads
extension-libs/platform-threads/djinni/platform-threads.djinni
0 → 100644
View file @
3a1c6421
# Platform service providing pluggable access to thread functionality
# which may vary by platform. Some language runtimes don't interact
# well with threads they didn't create, so this interface can be used
# as a factory for threads which can freely call across languages
# without issues.
platform_threads = interface +o +j +c {
# Creates and starts a new thread which will call the given function.
create_thread(name: string, func: thread_func);
# Determines whether the calling thread is the main UI thread of the
# app. Some platforms do not have a notion of a main thread, in which
# case this method returns null.
is_main_thread(): optional<bool>;
}
# Function to call on a thread created by platform interface.
thread_func = interface +c {
# Will be run on thread start. The thread will exit when this returns.
run();
}
extension-libs/platform-threads/java/com/dropbox/djinni/extension_libs/platform_threads/JavaPlatformThreads.java
0 → 100644
View file @
3a1c6421
//
// Copyright 2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
// Note: This is a sample implementation which interacts with Djinni-generated code.
// You may need to adjust names and packages to match the settings of code
// generation in your project. You may also need to add a catch clause if you
// configure Djinni to declare checked exceptions on generated methods.
//
package
com.dropbox.djinni.extension_libs.platform_threads
;
import
com.dropbox.djinni.generated.PlatformThreads
;
import
javax.annotation.CheckForNull
;
import
javax.annotation.Nonnull
;
import
javax.annotation.Nullable
;
/**
* Cross-language platform thread implementation using java.thread.Thread.
* Create a subclass and override configureThread() to customize the created threads.
*/
public
class
JavaPlatformThreads
extends
PlatformThreads
{
/**
* Creates an instance.
*/
public
JavaPlatformThreads
()
{}
/** Creates and starts a new thread which will call the given function. */
@Override
public
void
createThread
(
@Nonnull
String
name
,
@Nonnull
ThreadFunc
func
)
{
final
ThreadFunc
passFunc
=
func
;
Thread
thread
=
new
Thread
(
new
Runnable
()
{
@Override
public
void
run
()
{
passFunc
.
run
();
}
},
name
);
thread
.
setDaemon
(
true
);
configureThread
(
thread
);
thread
.
start
();
}
/**
* Determines whether the calling thread is the main UI thread of the
* app. Some platforms do not have a notion of a main thread, in which
* case this method returns null.
*
* This implementation returns null since Java doesn't have any default
* notion of a main/UI thread. Platform-specific subclasses may override.
*/
@Override
@CheckForNull
public
Boolean
isMainThread
()
{
return
null
;
}
/**
* Called after each thread is created, but before it is started.
* The default implementation does nothing, resulting in a default thread configuration.
*/
protected
void
configureThread
(
Thread
thread
)
{}
}
extension-libs/platform-threads/objc/DJIObjCPlatformThreads.h
0 → 100644
View file @
3a1c6421
//
// Copyright 2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
// Note: This is a sample implementation which interacts with Djinni-generated code.
// You may need to adjust names or include paths to match the settings of code
// generation in your project.
//
#include "DBPlatformThreads.h"
typedef
void
(
^
__nullable
DJIObjCPlatformThreadsConfigBlock
)(
NSThread
*
__nonnull
thread
);
typedef
void
(
^
__nonnull
DJIThreadFuncBlock
)();
/**
* Cross-language platform thread implementation using NSThread.
*/
@interface
DJIObjCPlatformThreads
:
NSObject
<
DBPlatformThreads
>
-
(
nullable
instancetype
)
init
__attribute__
((
unavailable
(
"Please use factory method instead."
)));
/** Creates an object which produces threads with default configuration. */
+
(
nullable
DJIObjCPlatformThreads
*
)
platformThreads
;
/**
* Creates an object which calls the given block on each thread after it's created,
* but before it's started. A nil block will be ignored.
*/
+
(
nullable
DJIObjCPlatformThreads
*
)
platformThreadsWithConfigBlock
:(
DJIObjCPlatformThreadsConfigBlock
)
block
;
/** Creates and starts a new thread which will call the given function. */
-
(
void
)
createThread
:(
nonnull
NSString
*
)
name
func
:(
nonnull
DBThreadFunc
*
)
func
;
/** Creates and starts a new thread which will call the given block. */
-
(
void
)
createThread
:(
nonnull
NSString
*
)
name
block
:(
DJIThreadFuncBlock
)
block
;
/**
* Determines whether the calling thread is the main UI thread of the
* app. Some platforms do not have a notion of a main thread, in which
* case this method returns null.
*
* This implementation returns YES or NO depending on NSThread's notion
* of the main thread.
*/
-
(
nonnull
NSNumber
*
)
isMainThread
;
@end
extension-libs/platform-threads/objc/DJIObjCPlatformThreads.m
0 → 100644
View file @
3a1c6421
//
// Copyright 2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "DJIObjCPlatformThreads.h"
#include "DBThreadFunc.h"
@interface
DJIObjCPlatformThreadsInternalFunc
:
DBThreadFunc
-
(
instancetype
)
initWithBlock
:(
DJIThreadFuncBlock
)
block
;
-
(
void
)
run
;
@end
@implementation
DJIObjCPlatformThreadsInternalFunc
{
DJIThreadFuncBlock
_runBlock
;
}
-
(
instancetype
)
initWithBlock
:(
DJIThreadFuncBlock
)
block
{
if
(
self
=
[
super
init
])
{
_runBlock
=
[
block
copy
];
}
return
self
;
}
-
(
void
)
run
{
_runBlock
();
}
@end
@implementation
DJIObjCPlatformThreads
{
DJIObjCPlatformThreadsConfigBlock
_cfgBlock
;
}
-
(
id
)
init
__attribute__
((
unavailable
))
{
return
nil
;
}
-
(
nullable
instancetype
)
initWithConfigBlock
:(
DJIObjCPlatformThreadsConfigBlock
)
block
{
if
(
self
=
[
super
init
])
{
_cfgBlock
=
[
block
copy
];
}
return
self
;
}
+
(
nullable
DJIObjCPlatformThreads
*
)
platformThreads
{
return
[
DJIObjCPlatformThreads
platformThreadsWithConfigBlock
:
nil
];
}
+
(
nullable
DJIObjCPlatformThreads
*
)
platformThreadsWithConfigBlock
:(
DJIObjCPlatformThreadsConfigBlock
)
block
{
return
[[
DJIObjCPlatformThreads
alloc
]
initWithConfigBlock
:
block
];
}
-
(
void
)
createThread
:(
nonnull
NSString
*
)
name
func
:(
nonnull
DBThreadFunc
*
)
func
{
NSThread
*
thread
=
[[
NSThread
alloc
]
initWithTarget
:
func
selector
:
@selector
(
run
)
object
:
nil
];
thread
.
name
=
name
;
if
(
_cfgBlock
)
{
_cfgBlock
(
thread
);
}
[
thread
start
];
}
-
(
void
)
createThread
:(
nonnull
NSString
*
)
name
block
:(
DJIThreadFuncBlock
)
block
{
[
self
createThread
:
name
func
:[[
DJIObjCPlatformThreadsInternalFunc
alloc
]
initWithBlock
:
block
]];
}
-
(
nonnull
NSNumber
*
)
isMainThread
{
return
[
NSNumber
numberWithBool
:[
NSThread
isMainThread
]];
}
@end
extension-libs/platform-threads/platform-threads.gyp
0 → 100644
View file @
3a1c6421
{
"targets": [
{
"target_name": "thread_cpp",
"type": "static_library",
"sources": [
"cpp/thread_impl.hpp",
],
"include_dirs": [
"cpp",
],
"direct_dependent_settings": {
"include_dirs": [
"cpp",
],
},
},
{
"target_name": "thread_objc",
"type": "static_library",
"xcode_settings": {
"CLANG_ENABLE_OBJC_ARC": "YES",
},
"sources": [
"objc/DJIThreadFactoryImpl.h",
"objc/DJIThreadFactoryImpl.m",
],
"include_dirs": [
"objc",
],
"direct_dependent_settings": {
"include_dirs": [
"objc",
],
},
},
# Java sources are in java/ and android/
# Gyp doesn't include native support for Java.
],
}
src/.idea/modules.xml
View file @
3a1c6421
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
<project
version=
"4"
>
<project
version=
"4"
>
<component
name=
"ProjectModuleManager"
>
<component
name=
"ProjectModuleManager"
>
<modules>
<modules>
<module
fileurl=
"file://$PROJECT_DIR$/../extension-libs/extension-libs.iml"
filepath=
"$PROJECT_DIR$/../extension-libs/extension-libs.iml"
/>
<module
fileurl=
"file://$PROJECT_DIR$/.idea/modules/src.iml"
filepath=
"$PROJECT_DIR$/.idea/modules/src.iml"
/>
<module
fileurl=
"file://$PROJECT_DIR$/.idea/modules/src.iml"
filepath=
"$PROJECT_DIR$/.idea/modules/src.iml"
/>
<module
fileurl=
"file://$PROJECT_DIR$/.idea/modules/src-build.iml"
filepath=
"$PROJECT_DIR$/.idea/modules/src-build.iml"
/>
<module
fileurl=
"file://$PROJECT_DIR$/.idea/modules/src-build.iml"
filepath=
"$PROJECT_DIR$/.idea/modules/src-build.iml"
/>
<module
fileurl=
"file://$PROJECT_DIR$/../support-lib/support-lib.iml"
filepath=
"$PROJECT_DIR$/../support-lib/support-lib.iml"
/>
<module
fileurl=
"file://$PROJECT_DIR$/../support-lib/support-lib.iml"
filepath=
"$PROJECT_DIR$/../support-lib/support-lib.iml"
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment