Skip to content

Commit c006be9

Browse files
committed
feat: implement multithreading
1 parent fd5f7d0 commit c006be9

File tree

4 files changed

+160
-45
lines changed

4 files changed

+160
-45
lines changed

cpp/NativeBcryptCppTurboModule.cpp

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,77 @@
11
#include "NativeBcryptCppTurboModule.h"
2-
//#import <QuartzCore/QuartzCore.h>
2+
#include <thread>
33

4+
namespace facebook::react
5+
{
6+
NativeBcryptCppTurboModule::NativeBcryptCppTurboModule(std::shared_ptr<CallInvoker> jsinvoker) : NativeBcryptCppCxxSpec<NativeBcryptCppTurboModule>(std::move(jsinvoker)) {}
47

5-
6-
namespace facebook::react {
7-
NativeBcryptCppTurboModule::NativeBcryptCppTurboModule(std::shared_ptr<CallInvoker> jsinvoker): NativeBcryptCppCxxSpec<NativeBcryptCppTurboModule>(std::move(jsinvoker)) {}
8-
9-
jsi::Value NativeBcryptCppTurboModule::generateHash(jsi::Runtime &rt, std::string password, double workload) {
10-
return jsi::Value::undefined();
8+
jsi::Value NativeBcryptCppTurboModule::generateHash(jsi::Runtime &rt, std::string password, double workload)
9+
{
10+
jsi::Function promiseConstructor = rt.global().getPropertyAsFunction(rt, "Promise");
11+
12+
return promiseConstructor.callAsConstructor(rt,
13+
jsi::Function::createFromHostFunction(
14+
rt,
15+
jsi::PropNameID::forAscii(rt, "promiseArg"),
16+
2,
17+
[password, workload, jsInvoker = jsInvoker_](
18+
jsi::Runtime &runtime,
19+
const jsi::Value &thisValue,
20+
const jsi::Value *arguments,
21+
std::size_t count) -> jsi::Value
22+
{
23+
auto resolverValue = std::make_shared<jsi::Value>((arguments[0].asObject(runtime)));
24+
25+
std::thread([password, workload, resolverValue = std::move(resolverValue), jsInvoker, &runtime]()
26+
{
27+
std::string hash = bcrypt::generateHash(password, workload);
28+
// Post back to JS thread
29+
jsInvoker->invokeAsync([resolverValue, hash, &runtime]() {
30+
resolverValue->asObject(runtime).asFunction(runtime).call(runtime, hash);
31+
}); })
32+
.detach();
33+
return jsi::Value::undefined();
34+
})
35+
36+
);
1137
}
1238

13-
14-
jsi::Value NativeBcryptCppTurboModule::validatePassword(jsi::Runtime &rt, std::string password, std::string hash) {
15-
return jsi::Value::undefined();
39+
jsi::Value NativeBcryptCppTurboModule::validatePassword(jsi::Runtime &rt, std::string password, std::string hash)
40+
{
41+
jsi::Function promiseConstructor = rt.global().getPropertyAsFunction(rt, "Promise");
42+
43+
return promiseConstructor.callAsConstructor(rt,
44+
jsi::Function::createFromHostFunction(
45+
rt,
46+
jsi::PropNameID::forAscii(rt, "promiseArg"),
47+
2,
48+
[password, hash, jsInvoker = jsInvoker_](
49+
jsi::Runtime &runtime,
50+
const jsi::Value &thisValue,
51+
const jsi::Value *arguments,
52+
std::size_t count) -> jsi::Value
53+
{
54+
auto resolverValue = std::make_shared<jsi::Value>((arguments[0].asObject(runtime)));
55+
56+
std::thread([password, hash, resolverValue = std::move(resolverValue), jsInvoker, &runtime]()
57+
{
58+
bool isValid = bcrypt::validatePassword(password, hash);
59+
// Post back to JS thread
60+
jsInvoker->invokeAsync([resolverValue, isValid, &runtime]() {
61+
resolverValue->asObject(runtime).asFunction(runtime).call(runtime, isValid);
62+
}); })
63+
.detach();
64+
return jsi::Value::undefined();
65+
})
66+
67+
);
1668
}
17-
std::string NativeBcryptCppTurboModule::generateHashSync(jsi::Runtime &rt, std::string password, double workload){
18-
19-
std::string generatedHash = bcrypt::generateHash(password, workload);
20-
return generatedHash;
69+
std::string NativeBcryptCppTurboModule::generateHashSync(jsi::Runtime &rt, std::string password, double workload)
70+
{
71+
return bcrypt::generateHash(password, workload);
2172
}
22-
bool NativeBcryptCppTurboModule::validatePasswordSync(jsi::Runtime &rt, std::string password, std::string hash) {
73+
bool NativeBcryptCppTurboModule::validatePasswordSync(jsi::Runtime &rt, std::string password, std::string hash)
74+
{
2375
return bcrypt::validatePassword(password, hash);
2476
}
2577

example/ios/BcryptCppExample.xcodeproj/project.pbxproj

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
00E356EE1AD99517003FC87E /* BcryptCppExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BcryptCppExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3232
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3333
00E356F21AD99517003FC87E /* BcryptCppExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BcryptCppExampleTests.m; sourceTree = "<group>"; };
34-
0580ABFB39ADC1A50C1EF3C7 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = BcryptCppExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
34+
0580ABFB39ADC1A50C1EF3C7 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = BcryptCppExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
3535
13B07F961A680F5B00A75B9A /* BcryptCppExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BcryptCppExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
3636
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = BcryptCppExample/AppDelegate.h; sourceTree = "<group>"; };
3737
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = BcryptCppExample/AppDelegate.mm; sourceTree = "<group>"; };
@@ -472,6 +472,7 @@
472472
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
473473
CLANG_ENABLE_MODULES = YES;
474474
CURRENT_PROJECT_VERSION = 1;
475+
DEVELOPMENT_TEAM = 99NF33M5QW;
475476
ENABLE_BITCODE = NO;
476477
INFOPLIST_FILE = BcryptCppExample/Info.plist;
477478
LD_RUNPATH_SEARCH_PATHS = (
@@ -499,6 +500,7 @@
499500
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
500501
CLANG_ENABLE_MODULES = YES;
501502
CURRENT_PROJECT_VERSION = 1;
503+
DEVELOPMENT_TEAM = 99NF33M5QW;
502504
INFOPLIST_FILE = BcryptCppExample/Info.plist;
503505
LD_RUNPATH_SEARCH_PATHS = (
504506
"$(inherited)",
@@ -590,10 +592,7 @@
590592
"-DFOLLY_CFG_NO_COROUTINES=1",
591593
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
592594
);
593-
OTHER_LDFLAGS = (
594-
"$(inherited)",
595-
" ",
596-
);
595+
OTHER_LDFLAGS = "$(inherited) ";
597596
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
598597
SDKROOT = iphoneos;
599598
USE_HERMES = true;
@@ -665,10 +664,7 @@
665664
"-DFOLLY_CFG_NO_COROUTINES=1",
666665
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
667666
);
668-
OTHER_LDFLAGS = (
669-
"$(inherited)",
670-
" ",
671-
);
667+
OTHER_LDFLAGS = "$(inherited) ";
672668
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
673669
SDKROOT = iphoneos;
674670
USE_HERMES = true;

example/src/App.tsx

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,61 @@ import {
55
validatePassword,
66
validatePasswordSync,
77
} from 'react-native-bcrypt-cpp';
8+
import { MovingRectangle } from './MovingRectangle';
9+
10+
const workload = 15;
11+
const password = 'asdcds-sdjakl12313841skdnanczdeioaj';
12+
const hash = '$2b$15$wX0mKtpwGwzdfbz099nUnu5R.NN/huUK9XBra0sS4xj4XfjfPOkzO';
13+
14+
async function measureTime<T>(fn: () => T): Promise<T> {
15+
const start = performance.now();
16+
const res = await fn();
17+
const end = performance.now();
18+
const timeTaken = end - start;
19+
console.log('Time taken :', timeTaken, 'ms');
20+
return res;
21+
}
822

923
export default function App() {
1024
return (
1125
<View style={styles.container}>
26+
<MovingRectangle />
1227
<Button
1328
title="Generate Hash"
1429
onPress={async () => {
15-
const password = 'password';
16-
const workload = 10;
17-
const hash = await generateHash(password, workload);
18-
console.log(hash);
30+
const generatedHash = await measureTime(() =>
31+
generateHash(password, workload)
32+
);
33+
console.log('Generated hash:', generatedHash);
1934
}}
2035
/>
2136
<Button
22-
title="Generate Hash Sync"
23-
onPress={() => console.log(generateHashSync('password', 10))}
37+
title="Validate Password"
38+
onPress={async () => {
39+
const isValid = await measureTime(() =>
40+
validatePassword(password, hash)
41+
);
42+
console.log('isValid', isValid);
43+
}}
2444
/>
25-
2645
<Button
27-
title="Validate Password"
46+
title="Generate Hash Sync"
2847
onPress={async () => {
29-
const password = 'password';
30-
const hash =
31-
'$2a$10$5e1Q8Bj1JWz5J9zQ7H5v3OjL2wz1I0Q9zZ6QzZ1Z1Z1Z1Z1Z1Z1Z1';
32-
const isValid = await validatePassword(password, hash);
33-
console.log(isValid);
48+
const generatedHash = await measureTime(() =>
49+
generateHashSync(password, workload)
50+
);
51+
console.log('Generated hash:', generatedHash);
3452
}}
3553
/>
3654

3755
<Button
3856
title="Validate Password Sync"
39-
onPress={() =>
40-
console.log(
41-
validatePasswordSync(
42-
'password',
43-
'$2a$10$5e1Q8Bj1JWz5J9zQ7H5v3OjL2wz1I0Q9zZ6QzZ1Z1Z1Z1Z1Z1Z1'
44-
)
45-
)
46-
}
57+
onPress={async () => {
58+
const isValid = await measureTime(() =>
59+
validatePasswordSync(password, hash)
60+
);
61+
console.log('isValid', isValid);
62+
}}
4763
/>
4864
</View>
4965
);

example/src/MovingRectangle.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { useEffect, useRef } from 'react';
2+
import { Animated, StyleSheet, View } from 'react-native';
3+
4+
export const MovingRectangle = () => {
5+
const animationValue = useRef(new Animated.Value(0)).current;
6+
7+
useEffect(() => {
8+
const animate = () => {
9+
Animated.loop(
10+
Animated.sequence([
11+
Animated.timing(animationValue, {
12+
toValue: 100,
13+
duration: 300,
14+
useNativeDriver: false, // This runs the animation on the JS thread
15+
}),
16+
Animated.timing(animationValue, {
17+
toValue: 0,
18+
duration: 300,
19+
useNativeDriver: false, // This runs the animation on the JS thread
20+
}),
21+
])
22+
).start();
23+
};
24+
25+
animate();
26+
}, [animationValue]);
27+
28+
return (
29+
<View style={styles.container}>
30+
<Animated.View
31+
style={[
32+
styles.rectangle,
33+
{ transform: [{ translateX: animationValue }] },
34+
]}
35+
/>
36+
</View>
37+
);
38+
};
39+
40+
const styles = StyleSheet.create({
41+
container: {
42+
justifyContent: 'center',
43+
alignItems: 'center',
44+
marginBottom: 50,
45+
},
46+
rectangle: {
47+
width: 100,
48+
height: 100,
49+
backgroundColor: 'blue',
50+
},
51+
});

0 commit comments

Comments
 (0)