Skip to content
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

Spawn behaviours with a dynamic cown set #23

Merged
merged 16 commits into from
Aug 24, 2023

Conversation

marioskogias
Copy link
Collaborator

No description provided.

Copy link
Member

@mjp41 mjp41 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Could you improve the test coverage?

src/rt/cpp/when.h Outdated Show resolved Hide resolved
src/rt/cpp/when.h Outdated Show resolved Hide resolved
src/rt/cpp/when.h Outdated Show resolved Hide resolved
src/rt/cpp/when.h Outdated Show resolved Hide resolved
Comment on lines 63 to 65
auto log3 = make_cown<Body2>(1);

cown_ptr_span<Body2> t2{&log3, 1};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this dead code?

Comment on lines 85 to 87
auto log3 = make_cown<Body2>(1);

cown_ptr_span<Body2> t2{&log3, 1};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this dead code?

test/func/dynamic-cownset/dynamic-cownset.cc Outdated Show resolved Hide resolved

cown_ptr_span<Body2> t2{&log3, 1};

when(t1, log1) << [=](acquired_cown_span<Body1> ca, acquired_cown<Body1> a) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a few more complex sequences here to ensure coverage of first and last being different things:

  • span, cown
  • cown, span
  • span, span
  • span, cown, span
  • cown, span, cown

test/func/dynamic-cownset/dynamic-cownset.cc Show resolved Hide resolved
@@ -0,0 +1,102 @@
// Copyright Microsoft and Project Verona Contributors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add test coverage for move versus copy of cown span

  when (span) { ... }

versus

  when (std::move(span)) { ... }

Comment on lines 131 to 150
size_t actual_size =
ptr_span.length * sizeof(ActualCown<std::remove_const_t<T>>*);
size_t acq_size =
ptr_span.length * sizeof(acquired_cown<std::remove_const_t<T>>);
span.array = reinterpret_cast<ActualCown<std::remove_const_t<T>>**>(
snmalloc::ThreadAlloc::get().alloc(actual_size + acq_size));

for (size_t i = 0; i < ptr_span.length; i++)
{
span.array[i] = ptr_span.array[i].allocated_cown;
}
span.length = ptr_span.length;

acq_array =
reinterpret_cast<acquired_cown<T>*>((char*)(span.array) + actual_size);

for (size_t i = 0; i < ptr_span.length; i++)
{
new (&acq_array[i]) acquired_cown<T>(*ptr_span.array[i].allocated_cown);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you factor out the code duplication here from the above constructor. Thanks

Copy link
Member

@mjp41 mjp41 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly minute stuff now. Would be nice if there were a few more comments. But it's looking great.

src/rt/cpp/when.h Outdated Show resolved Hide resolved
src/rt/cpp/when.h Show resolved Hide resolved
src/rt/cpp/when.h Outdated Show resolved Hide resolved
Comment on lines 59 to 62
cown_ptr_span(cown_ptr_span&& old) = delete;
cown_ptr_span& operator=(cown_ptr_span&&) = delete;
cown_ptr_span& operator=(const cown_ptr_span&) = delete;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these operators deleted? Could you add a comment to explain.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to be deleted. They are not used in the current codebase. So, I marked them as deleted to avoid bugs in auto generated. I'll add a comment to clarify.

{
array = reinterpret_cast<cown_ptr<T>*>(
snmalloc::ThreadAlloc::get().alloc(length * sizeof(cown_ptr<T>*)));
memset(array, 0, length * sizeof(cown_ptr<T>*));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why memset? The next loop overwrites everything.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the cown_ptr copy assignment operator does a clear() first. I'll remove the memset and call the copy constructor with new (&array[i]) cown_ptr<T>(arr[i]) instead.

src/rt/cpp/when.h Outdated Show resolved Hide resolved
template<typename T>
struct cown_ptr_span
{
cown_ptr<T>* array;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add comments about ownership here? Is this class opening the underlying cownptrs or borrowing them. Explaining that, and then adding comments elsewhere.

Does std::move make sense if they are borrowed? Hadn't thought about this for my earlier review.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's clearer if cown_ptr_span always owns the included cowns. This can happen either by allocating a new cown_ptr array and incrementing the reference count, or by using the template parameter and passing an array of cown_ptr that already holds the ownership.

I added a comment that explains that.

* allocated array.
*/
template<typename T>
struct cown_ptr_span
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I have one minor thing given this is an owning array. I think we should perhaps call it: cown_array. I think of span as borrowed, and not owning the underlying memory. But this does, so I think the current name will given the wrong idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I can do that. I thought that owning made more sense and made things simpler. Alternatively, we can keep the span semantics and prevent from passing it with move. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think owning is the right choice. Let's rename.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack

src/rt/cpp/when.h Outdated Show resolved Hide resolved
ActualCownSpan& operator=(ActualCownSpan&& old)
{
if (array)
snmalloc::ThreadAlloc::get().dealloc(array);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is performing deallocation, so doesn't this require ownership?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This array holds ActualCown<T>, though, not cown_ptr<T>. If I understand correctly, when this array is constructed there is no reference count increase.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, yeah, so ActualCown is kind of borrowing from the underlying cown_ptr. Makes sense, do you think you could add a comment, so we don't get confused again. Possibly add a comment to ActualCown too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a destructor to deallocate the array too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. ActualCown borrows from the underlying cown_array. I'll add the comment.

You are also correct about the confusion with the dealloc. This is wrong and it shouldn't be there. The lifetime of the ActualCownSpan is always the same as the AccessBatch. The memory the span uses is managed by the AccessBatch constructors and destructors. There is no need for a move assignment operator. I'll remove that.

The lifetime of the Access and AccessBatch goes all the way till after the execution of the behaviour.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this the case, should the ActualCownSpan be defined inside the AccessBatch?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. So ActualCownSpan is different to ActualCown. ActualCown is the Verona runtimes view of a cown, where as ActualCownSpan is part of the behaviour structure. I think moving it into AccessBatch makes sense, I also wonder if it should be Actual..., but differently named?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it should be ActualCownPtrSpan since it's an array of pointers to ActualCown.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore it. It's not necessary and it's only confusing. I'm removing it completely.

Copy link
Member

@mjp41 mjp41 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, could you remove the dead code.

Comment on lines 60 to 89
#if 0
/**
* This is a non-owning span of ActualCown pointers
* Its lifetime is always the same as the AccessBatch.
*/
struct ActualCownPtrSpan
{
ActualCown<std::remove_const_t<T>>** array;
size_t length;

void clear()
{
length = 0;
array = nullptr;
}

ActualCownPtrSpan()
{
clear();
}

ActualCownPtrSpan(ActualCownPtrSpan&& old)
{
length = old.length;
array = old.array;
old.clear();
}
};
#endif

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#if 0
/**
* This is a non-owning span of ActualCown pointers
* Its lifetime is always the same as the AccessBatch.
*/
struct ActualCownPtrSpan
{
ActualCown<std::remove_const_t<T>>** array;
size_t length;
void clear()
{
length = 0;
array = nullptr;
}
ActualCownPtrSpan()
{
clear();
}
ActualCownPtrSpan(ActualCownPtrSpan&& old)
{
length = old.length;
array = old.array;
old.clear();
}
};
#endif

Copy link
Member

@mjp41 mjp41 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@marioskogias marioskogias merged commit ab42a9f into microsoft:main Aug 24, 2023
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants