Ownership
RAII Scope
RAII ties a resource's lifetime to an object's scope.
RAII
RAII means resource acquisition is initialization: acquire in the constructor and release in the destructor.
RAII Scope
raii_scope.cpp
Replay: real traced execution (multi-file project)
#include <iostream>
#include <string>
class ScopeLog {
private:
std::string name;
public:
ScopeLog(std::string label) {
name = label;
std::cout << "enter=" << name << std::endl;
}
~ScopeLog() {
std::cout << "leave=" << name << std::endl;
}
};
int runJob(std::string label, int workUnits) {
ScopeLog scope(label);
int total = 0;
for (int i = 1; i <= workUnits; i++) {
total += i;
}
return total;
}
int main() {
std::string label = "load";
int workUnits = 3;
int total = runJob(label, workUnits);
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <string>
class ScopeLog {
private:
std::string name;
public:
ScopeLog(std::string label) {
name = label;
std::cout << "enter=" << name << std::endl;
}
~ScopeLog() {
std::cout << "leave=" << name << std::endl;
}
};
int runJob(std::string label, int workUnits) {
ScopeLog scope(label);
int total = 0;
for (int i = 1; i <= workUnits; i++) {
total += i;
}
return total;
}
int main() {
std::string label = "save";
int workUnits = 3;
int total = runJob(label, workUnits);
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <string>
class ScopeLog {
private:
std::string name;
public:
ScopeLog(std::string label) {
name = label;
std::cout << "enter=" << name << std::endl;
}
~ScopeLog() {
std::cout << "leave=" << name << std::endl;
}
};
int runJob(std::string label, int workUnits) {
ScopeLog scope(label);
int total = 0;
for (int i = 1; i <= workUnits; i++) {
total += i;
}
return total;
}
int main() {
std::string label = "sync";
int workUnits = 3;
int total = runJob(label, workUnits);
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <string>
class ScopeLog {
private:
std::string name;
public:
ScopeLog(std::string label) {
name = label;
std::cout << "enter=" << name << std::endl;
}
~ScopeLog() {
std::cout << "leave=" << name << std::endl;
}
};
int runJob(std::string label, int workUnits) {
ScopeLog scope(label);
int total = 0;
for (int i = 1; i <= workUnits; i++) {
total += i;
}
return total;
}
int main() {
std::string label = "load";
int workUnits = 1;
int total = runJob(label, workUnits);
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <string>
class ScopeLog {
private:
std::string name;
public:
ScopeLog(std::string label) {
name = label;
std::cout << "enter=" << name << std::endl;
}
~ScopeLog() {
std::cout << "leave=" << name << std::endl;
}
};
int runJob(std::string label, int workUnits) {
ScopeLog scope(label);
int total = 0;
for (int i = 1; i <= workUnits; i++) {
total += i;
}
return total;
}
int main() {
std::string label = "load";
int workUnits = 5;
int total = runJob(label, workUnits);
std::cout << "total=" << total << std::endl;
return 0;
}
label ← load, workUnits ← 3
28int main() {29 std::string label→ load = "load"; //@label="save", "sync"30 int workUnits→ 3 = 3; //@workUnits=1, 53132 int total = runJob(labelload, workUnits3);int runJob(std::string label, int workUnits)
19int runJob(std::string labelload, int workUnits3) {20 ScopeLog scope(labelload);21 int total = 0;ScopeLog(std::string label)
8public:9 ScopeLog(std::string labelload) {10 name = labelload;11 std::cout << "enter=" << name << std::endl;12 }outputenter=loadscope ← (empty), total ← 0
19int runJob(std::string label, int workUnits) {20 ScopeLog scope→ (empty)(labelload);21 int total→ 0 = 0;22 for (int i = 1; i <= workUnits; i++) {total ← 1
pass 1 of 321int total = 0;22for (int i1 = 1; i <= workUnits3; i++) {23 total→ 1 += i1;24}All 3 passes — pass 1 is the card above pass itotal1 1 0 → 1 2 2 1 → 3 3 3 3 → 6 return total;
24 }25 return total6;26}~ScopeLog()
14~ScopeLog() {15 std::cout << "leave=" << name << std::endl;16}outputleave=loadtotal ← 6
32 int total→ 6 = runJob(labelload, workUnits3);3334 std::cout << "total=" << total6 << std::endl;35 return 0;36}outputtotal=6
label ← save, workUnits ← 3
28int main() {29 std::string label→ save = "save";30 int workUnits→ 3 = 3;3132 int total = runJob(labelsave, workUnits3);int runJob(std::string label, int workUnits)
19int runJob(std::string labelsave, int workUnits3) {20 ScopeLog scope(labelsave);21 int total = 0;ScopeLog(std::string label)
8public:9 ScopeLog(std::string labelsave) {10 name = labelsave;11 std::cout << "enter=" << name << std::endl;12 }outputenter=savescope ← (empty), total ← 0
19int runJob(std::string label, int workUnits) {20 ScopeLog scope→ (empty)(labelsave);21 int total→ 0 = 0;22 for (int i = 1; i <= workUnits; i++) {total ← 1
pass 1 of 321int total = 0;22for (int i1 = 1; i <= workUnits3; i++) {23 total→ 1 += i1;24}All 3 passes — pass 1 is the card above pass itotal1 1 0 → 1 2 2 1 → 3 3 3 3 → 6 return total;
24 }25 return total6;26}~ScopeLog()
14~ScopeLog() {15 std::cout << "leave=" << name << std::endl;16}outputleave=savetotal ← 6
32 int total→ 6 = runJob(labelsave, workUnits3);3334 std::cout << "total=" << total6 << std::endl;35 return 0;36}outputtotal=6
label ← sync, workUnits ← 3
28int main() {29 std::string label→ sync = "sync";30 int workUnits→ 3 = 3;3132 int total = runJob(labelsync, workUnits3);int runJob(std::string label, int workUnits)
19int runJob(std::string labelsync, int workUnits3) {20 ScopeLog scope(labelsync);21 int total = 0;ScopeLog(std::string label)
8public:9 ScopeLog(std::string labelsync) {10 name = labelsync;11 std::cout << "enter=" << name << std::endl;12 }outputenter=syncscope ← (empty), total ← 0
19int runJob(std::string label, int workUnits) {20 ScopeLog scope→ (empty)(labelsync);21 int total→ 0 = 0;22 for (int i = 1; i <= workUnits; i++) {total ← 1
pass 1 of 321int total = 0;22for (int i1 = 1; i <= workUnits3; i++) {23 total→ 1 += i1;24}All 3 passes — pass 1 is the card above pass itotal1 1 0 → 1 2 2 1 → 3 3 3 3 → 6 return total;
24 }25 return total6;26}~ScopeLog()
14~ScopeLog() {15 std::cout << "leave=" << name << std::endl;16}outputleave=synctotal ← 6
32 int total→ 6 = runJob(labelsync, workUnits3);3334 std::cout << "total=" << total6 << std::endl;35 return 0;36}outputtotal=6
label ← load, workUnits ← 1
28int main() {29 std::string label→ load = "load";30 int workUnits→ 1 = 1;3132 int total = runJob(labelload, workUnits1);int runJob(std::string label, int workUnits)
19int runJob(std::string labelload, int workUnits1) {20 ScopeLog scope(labelload);21 int total = 0;ScopeLog(std::string label)
8public:9 ScopeLog(std::string labelload) {10 name = labelload;11 std::cout << "enter=" << name << std::endl;12 }outputenter=loadscope ← (empty), total ← 0
19int runJob(std::string label, int workUnits) {20 ScopeLog scope→ (empty)(labelload);21 int total→ 0 = 0;22 for (int i = 1; i <= workUnits; i++) {total ← 1
21int total = 0;22for (int i1 = 1; i <= workUnits1; i++) {23 total→ 1 += i1;24}return total;
24 }25 return total1;26}~ScopeLog()
14~ScopeLog() {15 std::cout << "leave=" << name << std::endl;16}outputleave=loadtotal ← 1
32 int total→ 1 = runJob(labelload, workUnits1);3334 std::cout << "total=" << total1 << std::endl;35 return 0;36}outputtotal=1
label ← load, workUnits ← 5
28int main() {29 std::string label→ load = "load";30 int workUnits→ 5 = 5;3132 int total = runJob(labelload, workUnits5);int runJob(std::string label, int workUnits)
19int runJob(std::string labelload, int workUnits5) {20 ScopeLog scope(labelload);21 int total = 0;ScopeLog(std::string label)
8public:9 ScopeLog(std::string labelload) {10 name = labelload;11 std::cout << "enter=" << name << std::endl;12 }outputenter=loadscope ← (empty), total ← 0
19int runJob(std::string label, int workUnits) {20 ScopeLog scope→ (empty)(labelload);21 int total→ 0 = 0;22 for (int i = 1; i <= workUnits; i++) {total ← 1
pass 1 of 521int total = 0;22for (int i1 = 1; i <= workUnits5; i++) {23 total→ 1 += i1;24}All 5 passes — pass 1 is the card above pass itotal1 1 0 → 1 2 2 1 → 3 3 3 3 → 6 4 4 6 → 10 5 5 10 → 15 return total;
24 }25 return total15;26}~ScopeLog()
14~ScopeLog() {15 std::cout << "leave=" << name << std::endl;16}outputleave=loadtotal ← 15
32 int total→ 15 = runJob(labelload, workUnits5);3334 std::cout << "total=" << total15 << std::endl;35 return 0;36}outputtotal=15
Enter, Work, Leave
runJobcreatesScopeLog scope(label).- The constructor prints
enter=load. - The loop adds work units into
total. - Leaving
runJobdestroysscope. - The destructor prints
leave=loadautomatically. | Moment | What happens | | --- | --- | | enter scope | acquire/logload| | inside scope | calculate1 + 2 + 3| | leave scope | release/logload|
Exercise: raii_scope.cpp
Create a scope logger that prints on entry and exit while a small job computes a total